package impl

import (
	"adam2/internal/constants"
	"adam2/internal/domain"
	"adam2/internal/model"
	"adam2/internal/properties"
	iUitl "adam2/internal/util"
	pIo "anubis-framework/pkg/io"
	"anubis-framework/pkg/util"
	"bytes"
	"encoding/json"
	"github.com/jordan-wright/email"
	"github.com/shopspring/decimal"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"html/template"
	"io/ioutil"
	"math"
	"math/big"
	"net/smtp"
	"os"
	"os/exec"
	"strings"
	"time"
)

type Real9StockTransactionRecordServiceImpl struct {
	*BaseServiceImpl
}

// 获取service的实现类
func GetReal9StockTransactionRecordServiceImpl() *Real9StockTransactionRecordServiceImpl {
	return &Real9StockTransactionRecordServiceImpl{GetBaseServiceImpl()}
}

// 实时地判断买卖条件，给出交易建议
func (r *Real9StockTransactionRecordServiceImpl) RealTimeJudgeConditionAndGiveSuggestion() error {
	pIo.Infoln("开始实时地判断买卖条件，给出交易建议")

	// 上一轮的日期
	var finalDate *string

	for {
		// 定时任务
		var currentTime time.Time = time.Now()
		year, month, day := time.Now().Date()
		var beginTime time.Time = util.StringToTime(properties.Real9Properties_.ScheduleBeginTime)
		beginHour, beginMinute, beginSecond := beginTime.Clock()
		var endTime time.Time = util.StringToTime(properties.Real9Properties_.ScheduleEndTime)
		endHour, endMinute, endSecond := endTime.Clock()
		scheduleBeginTime := time.Date(year, month, day, beginHour, beginMinute, beginSecond, 0, time.Now().Location())
		scheduleEndTime := time.Date(year, month, day, endHour, endMinute, endSecond, 0, time.Now().Location())
		if currentTime.Before(scheduleBeginTime) {
			time.Sleep(5 * time.Minute)
			continue
		} else if currentTime.After(scheduleEndTime) {
			return nil
		} else {
			time.Sleep(time.Duration(properties.Real9Properties_.SleepMinute) * time.Minute)
		}

		/******************************************************************* 恢复数据 *******************************************************************/
		// 在使用实时数据的情况下，恢复为上一轮的数据
		if properties.Real9Properties_.UseRealData == true && finalDate != nil {
			r.RestoreReal9(finalDate)
		}

		// 查询所有交易日
		var dateList = r.getRealOrHistoryDate(properties.Real9Properties_.BeginDate, properties.Real9Properties_.EndDate)
		if dateList != nil && len(dateList) > 0 {
			for _, _date := range dateList {
				// 确定各种日期：每日、买入日/卖出日，统计日
				var everyDate *string = &_date
				var buyOrSelDate *string
				var statisticsDate *string

				if *everyDate == "2012-03-01" {
					pIo.Infoln("")
				}

				// 判断是否是一个月的第一个交易日
				if r.isBeginDate(_date) {
					buyOrSelDate = &_date
					statisticsDate = r._stockTransactionDataAllDaoImpl.FindLastDateByDate(_date)
					pIo.Infoln("当前日期是[%s]，是买入日/卖出日，统计日为[%s]", *buyOrSelDate, *statisticsDate)
				} else {
					pIo.Infoln("当前日期是[%s]，是每日", *everyDate)
				}

				/******************************************************************* 量化 *******************************************************************/

				// 每日---卖出之前更新real9_q_account
				r.updateQuantAccountBeforeSell(*everyDate)

				// 买入日---做统计日的工作：准备数据、过滤股票
				if buyOrSelDate != nil {
					// 统计日---准备数据
					r.prepareData(*statisticsDate)

					// 统计日---删除总市值不满足要求的股票
					r.deleteByTotalMarketValue(*statisticsDate)

					// 统计日---只保留总市值最小的(10*账号数量+4)只股票
					r.retainMinTotalMarketValue()
				}

				// 买入日---过滤股票
				if buyOrSelDate != nil {
					// 买入日---去除一字涨停版
					r.deleteOneWordLimitUp(*buyOrSelDate)

					// 买入日---删除开盘价不满足要求的股票
					r.deleteOpenPriceBottomLimit(*buyOrSelDate)
				}

				// 每日---解决之前卖出失败的情况
				r.sellQuantResolveFail(*everyDate)

				// 每日---退市卖出
				r.sellQuantDelist(*everyDate)

				// 卖出日---卖出
				if buyOrSelDate != nil {
					r.doQuantSell(*everyDate)
				}

				// 卖出日---在卖出之后更新real9_q_account
				if buyOrSelDate != nil {
					r.updateQuantAccountAfterSell(*everyDate)
				}

				// 买入日---买入
				if buyOrSelDate != nil {
					r.doQuantBuy(*everyDate)
				}

				// 买入日---在买入之后更新real9_q_account表
				if buyOrSelDate != nil {
					r.updateQuantAccountAfterBuy(*everyDate)
				}

				// 每日---向表real9_q_account_log中插入记录
				r.insertLog(*everyDate)

				// 每日---计算基础数据
				r.calculateBasicData(*everyDate)

				/******************************************************************* 优化 *******************************************************************/

				// 每日---卖出之前更新real9_o_account
				r.updateOptimizeAccountBeforeSell(*everyDate)

				// 每日---卖出之前卖出失败的
				r.doOptimizeResolveFailSell(*everyDate)

				// 每日---退市卖出
				r.doOptimizeDelistSell(*everyDate)

				// 卖出日---卖出
				if buyOrSelDate != nil {
					r.optimizeSell(*everyDate)
				}

				// 卖出日---在卖出之后更新real9_o_account
				r.updateOptimizeAccountAfterSell(*everyDate)

				// 买入日---买入
				if buyOrSelDate != nil {
					r.doOptimizeBuy(*everyDate)

					// 买入日---在买入之后更新real9_o_account表
					r.updateOptimizeAccountAfterBuy(*everyDate)
				}

				// 如果不是交易日，则判断是否在牛熊线之上；如果牛熊线之上，则加仓；如果在牛熊线之下，则减仓
				if buyOrSelDate == nil {
					//var underweight bool = r.underweight(*everyDate)
					r.underweight(*everyDate)
					// 在卖出之后更新real9_o_account
					r.updateOptimizeAccountAfterSell(*everyDate)

					//if !underweight {
					r.overweight(*everyDate)
					// 在买入之后更新optimize_account表
					r.updateOptimizeAccountAfterBuy(*everyDate)
					//}
				}

				// 每日---向表real9_o_account_log中插入记录
				r.insetReal9OptimizeAccountLog(*everyDate)

				// 每日---计算基础数据
				r.writeMa(*everyDate)
				r.writeBias(*everyDate)

				// 为恢复数据做准备
				finalDate = everyDate

				/******************************************************************* 比对 *******************************************************************/
				// 比对quant_*和real9_q_*表、optimize_*和real9_o_*表，如果有不一致，则退出程序
				r.compareQuantAndOptimizeWithReal9QuantAndReal9Optimize(*everyDate)
			}
		}

		// 打印交易建议，并发送邮件
		if properties.Real9Properties_.UseRealData == true {
			r.printAndMailSuggestion(properties.Real9Properties_.BeginDate)
		}

		// 如果使用历史数据，则只运行一次
		if properties.Real9Properties_.UseRealData == false {
			return nil
		}
	}

	pIo.Infoln("实时地判断买卖条件，给出交易建议结束")

	return nil
}

/***************************************************************************** 通用方法 *****************************************************************************/

// 判断是否是一个月的第一个交易日
func (r *Real9StockTransactionRecordServiceImpl) isBeginDate(everyDate string) bool {
	if properties.Real9Properties_.UseRealData == true {
		var lastDate *string = r._stockTransactionDataAllDaoImpl.FindLastDateByDate(everyDate)
		if util.StringToDate(everyDate).Month() > util.StringToDate(*lastDate).Month() {
			return true
		} else {
			return false
		}
	} else {
		var beginDateNumber int = r._stockIndexMonthDaoImpl.CountByBeginDate(everyDate)
		if beginDateNumber > 0 {
			return true
		} else {
			if everyDate == properties.Real9Properties_.RealtimeBeginDate {
				return true
			} else {
				return false
			}
		}
	}
}

// 查询所有交易日或者返回实时日期
func (r *Real9StockTransactionRecordServiceImpl) getRealOrHistoryDate(beginDate string, endDate string) []string {
	if properties.Real9Properties_.UseRealData == false {
		pIo.Infoln("查询所有交易日，范围从[%s]至[%s]", beginDate, endDate)

		var dateList, _ = r._stockTransactionDataAllDaoImpl.GetDistinctDateBetweenDateOrderByDateAsc(properties.Real9Properties_.BeginDate, properties.Real9Properties_.EndDate)
		return dateList
	} else {
		pIo.Infoln("返回实时日期")

		var dateList []string = []string{beginDate[0:4] + "-" + beginDate[4:6] + "-" + beginDate[6:]}
		return dateList
	}
}

// 根据股票代码和日期，获取实时收盘价或历史收盘价
func (r *Real9StockTransactionRecordServiceImpl) getRealOrHistoryClosePriceByByCodeAndDate(stockCode string, everyDate string) float64 {
	if properties.Real9Properties_.UseRealData == true {
		pIo.Infoln("根据股票代码[%s]和日期[%s]，获取实时收盘价", stockCode, everyDate)

		// 调用 Python 脚本
		cmd := exec.Command("python", properties.PythonProperties_.ManagePath, properties.PythonProperties_.PackageName, properties.PythonProperties_.FindRealStockTransactionDataByCodeMethodName, stockCode)

		// 捕获标准输出
		var out bytes.Buffer
		cmd.Stdout = &out

		// 运行命令并处理错误
		if _error := cmd.Run(); _error != nil {
			pIo.Infoln("调用python程序，获取股票时报错：", _error)
			return 0
		}

		// 解析返回的 JSON 数据
		var stockTransactionDataAll model.StockTransactionDataAll
		var realStockTransactionDataAll domain.RealStockTransactionDataAll
		if len(out.Bytes()) != 0 {
			reader := transform.NewReader(bytes.NewReader(out.Bytes()), simplifiedchinese.GBK.NewDecoder())
			all, err := ioutil.ReadAll(reader)
			if err != nil {
				pIo.Infoln("调用python程序，读取json数据时报错" + err.Error())
			}
			var result string = string(all)
			err = json.Unmarshal([]byte(result), &realStockTransactionDataAll)
			if err != nil {
				pIo.Infoln("调用python程序，转换json为struct数据时报错" + err.Error())
			}

			stockTransactionDataAll.Code = realStockTransactionDataAll.Code
			stockTransactionDataAll.HighestPrice = realStockTransactionDataAll.HighestPrice
			stockTransactionDataAll.LowestPrice = realStockTransactionDataAll.LowestPrice
			stockTransactionDataAll.OpenPrice = realStockTransactionDataAll.OpenPrice
			stockTransactionDataAll.ClosePrice = realStockTransactionDataAll.ClosePrice
			stockTransactionDataAll.Volume = realStockTransactionDataAll.Volume
			stockTransactionDataAll.Turnover = realStockTransactionDataAll.Turnover

			return stockTransactionDataAll.ClosePrice
		} else {
			pIo.Infoln("调用python程序，获取股票的数据为空")

			return 0
		}
	} else {
		pIo.Infoln("根据股票代码[%s]和日期[%s]，获取历史收盘价", stockCode, everyDate)

		var currentClosePrice float64 = r._stockTransactionDataAllDaoImpl.FindClosePriceByByCodeAndDate(stockCode, everyDate)

		return currentClosePrice
	}
}

// 根据股票代码和日期，获取实时收盘价或历史开盘价
func (r *Real9StockTransactionRecordServiceImpl) getRealOrHistoryOpenPriceByByCodeAndDate(stockCode string, everyDate string) float64 {
	if properties.Real9Properties_.UseRealData == true {
		pIo.Infoln("根据股票代码[%s]和日期[%s]，获取实时开盘价", stockCode, everyDate)

		// 调用 Python 脚本
		cmd := exec.Command("python", properties.PythonProperties_.ManagePath, properties.PythonProperties_.PackageName, properties.PythonProperties_.FindRealStockTransactionDataByCodeMethodName, stockCode)

		// 捕获标准输出
		var out bytes.Buffer
		cmd.Stdout = &out

		// 运行命令并处理错误
		if _error := cmd.Run(); _error != nil {
			pIo.Infoln("调用python程序，获取股票时报错：", _error)
			return 0
		}

		// 解析返回的 JSON 数据
		var stockTransactionDataAll model.StockTransactionDataAll
		var realStockTransactionDataAll domain.RealStockTransactionDataAll
		if len(out.Bytes()) != 0 {
			reader := transform.NewReader(bytes.NewReader(out.Bytes()), simplifiedchinese.GBK.NewDecoder())
			all, err := ioutil.ReadAll(reader)
			if err != nil {
				pIo.Infoln("调用python程序，读取json数据时报错" + err.Error())
			}
			var result string = string(all)
			err = json.Unmarshal([]byte(result), &realStockTransactionDataAll)
			if err != nil {
				pIo.Infoln("调用python程序，转换json为struct数据时报错" + err.Error())
			}

			stockTransactionDataAll.Code = realStockTransactionDataAll.Code
			stockTransactionDataAll.HighestPrice = realStockTransactionDataAll.HighestPrice
			stockTransactionDataAll.LowestPrice = realStockTransactionDataAll.LowestPrice
			stockTransactionDataAll.OpenPrice = realStockTransactionDataAll.OpenPrice
			stockTransactionDataAll.ClosePrice = realStockTransactionDataAll.ClosePrice
			stockTransactionDataAll.Volume = realStockTransactionDataAll.Volume
			stockTransactionDataAll.Turnover = realStockTransactionDataAll.Turnover

			return stockTransactionDataAll.ClosePrice
		} else {
			pIo.Infoln("调用python程序，获取股票的数据为空")

			return 0
		}
	} else {
		pIo.Infoln("根据股票代码[%s]和日期[%s]，获取历史开盘价", stockCode, everyDate)

		var currentClosePrice float64 = r._stockTransactionDataAllDaoImpl.FindOpenPriceByByCodeAndDate(stockCode, everyDate)
		return currentClosePrice
	}
}

// 根据股票代码和日期，获取实时数据或历史数据
func (r *Real9StockTransactionRecordServiceImpl) getRealOrHistoryStockTransactionDataAll(stockCode string, everyDate string) model.StockTransactionDataAll {
	if properties.Real9Properties_.UseRealData == true {
		pIo.Infoln("根据股票代码[%s]和日期[%s]，获取实时数据", stockCode, everyDate)

		// 调用 Python 脚本
		cmd := exec.Command("python", properties.PythonProperties_.ManagePath, properties.PythonProperties_.PackageName, properties.PythonProperties_.FindRealStockTransactionDataByCodeMethodName, stockCode)

		// 捕获标准输出
		var out bytes.Buffer
		cmd.Stdout = &out

		// 运行命令并处理错误
		if _error := cmd.Run(); _error != nil {
			pIo.Infoln("调用python程序，获取股票时报错：", _error)
			return model.StockTransactionDataAll{}
		}

		// 解析返回的 JSON 数据
		var stockTransactionDataAll model.StockTransactionDataAll
		var realStockTransactionDataAll domain.RealStockTransactionDataAll
		if len(out.Bytes()) != 0 {
			reader := transform.NewReader(bytes.NewReader(out.Bytes()), simplifiedchinese.GBK.NewDecoder())
			all, err := ioutil.ReadAll(reader)
			if err != nil {
				pIo.Infoln("调用python程序，读取json数据时报错" + err.Error())
			}
			var result string = string(all)
			err = json.Unmarshal([]byte(result), &realStockTransactionDataAll)
			if err != nil {
				pIo.Infoln("调用python程序，转换json为struct数据时报错" + err.Error())
			}

			// 如果日期不是当天，则可能是停牌
			var _date = util.StringToDate(realStockTransactionDataAll.Date[0:4] + "-" + realStockTransactionDataAll.Date[4:6] + "-" + realStockTransactionDataAll.Date[6:8])
			var _everyDate = util.StringToDate(everyDate)
			if !_date.Equal(_everyDate) {
				pIo.Infoln("调用python程序，获取股票为空，可能是停牌：" + stockCode)
				return model.StockTransactionDataAll{}
			}

			stockTransactionDataAll.Code = realStockTransactionDataAll.Code
			stockTransactionDataAll.Date = util.StringToDate(realStockTransactionDataAll.Date)
			stockTransactionDataAll.HighestPrice = realStockTransactionDataAll.HighestPrice
			stockTransactionDataAll.LowestPrice = realStockTransactionDataAll.LowestPrice
			stockTransactionDataAll.OpenPrice = realStockTransactionDataAll.OpenPrice
			stockTransactionDataAll.ClosePrice = realStockTransactionDataAll.ClosePrice
			stockTransactionDataAll.Volume = realStockTransactionDataAll.Volume
			stockTransactionDataAll.Turnover = realStockTransactionDataAll.Turnover
			var lastStockTransactionDataAll model.StockTransactionDataAll = r._stockTransactionDataAllDaoImpl.FindLastStockTransactionDataAllClosePriceByByCodeAndDate(realStockTransactionDataAll.Code, everyDate)
			stockTransactionDataAll.ChangeAmount = realStockTransactionDataAll.ClosePrice - lastStockTransactionDataAll.ClosePrice
			stockTransactionDataAll.ChangeRange = (realStockTransactionDataAll.ClosePrice - lastStockTransactionDataAll.ClosePrice) / lastStockTransactionDataAll.ClosePrice * 100

			return stockTransactionDataAll
		} else {
			pIo.Infoln("调用python程序，获取股票的数据为空")

			return model.StockTransactionDataAll{}
		}
	} else {
		pIo.Infoln("根据股票代码[%s]和日期[%s]，获取历史数据", stockCode, everyDate)

		var stockTransactionDataAll model.StockTransactionDataAll = r._stockTransactionDataAllDaoImpl.FindByCodeAndDate(stockCode, everyDate)
		return stockTransactionDataAll
	}
}

// 查询可以减仓的股票
func (r *Real9StockTransactionRecordServiceImpl) getRealOptimizeStockTransactRecordArrayByAccountNameAndDateAndSellNull(accountName string, everyDate string) model.Real9OptimizeStockTransactionRecordArray {
	if properties.Real9Properties_.UseRealData == true {
		pIo.Infoln("查询可以减仓的股票，获取实时数据，日期[%s]", everyDate)

		// 根据账户名称，查询real9_o_stock_transact_record表中未卖出的股票记录
		var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(accountName)
		if len(real9OptimizeStockTransactionRecordArray) == 0 {
			pIo.Infoln("日期为[%s]，账号[%s]没有可以减仓的股票", everyDate, accountName)
			return model.Real9OptimizeStockTransactionRecordArray{}
		}

		// 将code连接为字符串
		var codeArray []string
		for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
			codeArray = append(codeArray, real9OptimizeStockTransactionRecord.StockCode)
		}
		var codeString string = strings.Join(codeArray, ",")

		// 调用 Python 脚本
		cmd := exec.Command("python", properties.PythonProperties_.ManagePath, properties.PythonProperties_.PackageName, properties.PythonProperties_.FindRealCodeAndTotalMarketValueByCodeListMethodName, codeString)

		// 捕获标准输出
		var out bytes.Buffer
		cmd.Stdout = &out

		// 运行命令并处理错误
		if _error := cmd.Run(); _error != nil {
			pIo.Infoln("调用python程序，获取股票时报错：", _error)
			return model.Real9OptimizeStockTransactionRecordArray{}
		}

		// 解析返回的 JSON 数据
		var realStockTransactionDataAllArray []domain.RealStockTransactionDataAll
		if len(out.Bytes()) != 0 {
			reader := transform.NewReader(bytes.NewReader(out.Bytes()), simplifiedchinese.GBK.NewDecoder())
			all, err := ioutil.ReadAll(reader)
			if err != nil {
				pIo.Infoln("调用python程序，读取json数据时报错" + err.Error())
			}
			var result string = string(all)
			err = json.Unmarshal([]byte(result), &realStockTransactionDataAllArray)
			if err != nil {
				pIo.Infoln("调用python程序，转换json为struct数据时报错" + err.Error())
			}

			// 按照总市值降序排列
			if len(realStockTransactionDataAllArray) != 0 {
				var _real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = model.Real9OptimizeStockTransactionRecordArray{}
				n := len(realStockTransactionDataAllArray)
				for i := 0; i < n; i++ {
					for j := 0; j < n-i-1; j++ {
						if realStockTransactionDataAllArray[j].TotalMarketValue < realStockTransactionDataAllArray[j+1].TotalMarketValue {
							realStockTransactionDataAllArray[j], realStockTransactionDataAllArray[j+1] = realStockTransactionDataAllArray[j+1], realStockTransactionDataAllArray[j]
						}
					}
				}
				for _, realStockTransactionDataAll := range realStockTransactionDataAllArray {
					var real9OptimizeStockTransactionRecord model.Real9OptimizeStockTransactionRecord
					real9OptimizeStockTransactionRecord.StockCode = realStockTransactionDataAll.Code
					real9OptimizeStockTransactionRecord.AccountName = accountName
					var _real9OptimizeStockTransactionRecord model.Real9OptimizeStockTransactionRecord = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndStockCodeAndSellDateNull(accountName, real9OptimizeStockTransactionRecord.StockCode)
					real9OptimizeStockTransactionRecord.BuyPrice = _real9OptimizeStockTransactionRecord.BuyPrice
					real9OptimizeStockTransactionRecord.BuyAmount = _real9OptimizeStockTransactionRecord.BuyAmount
					real9OptimizeStockTransactionRecord.BuyDate = _real9OptimizeStockTransactionRecord.BuyDate
					_real9OptimizeStockTransactionRecordArray = append(_real9OptimizeStockTransactionRecordArray, &real9OptimizeStockTransactionRecord)
				}

				return _real9OptimizeStockTransactionRecordArray
			} else {
				pIo.Infoln("无法获取到股票的实时数据，无法减仓")
				return model.Real9OptimizeStockTransactionRecordArray{}
			}
		} else {
			pIo.Infoln("调用python程序，获取股票的数据为空")

			return model.Real9OptimizeStockTransactionRecordArray{}
		}
	} else {
		pIo.Infoln("查询可以减仓的股票，，获取历史数据，日期[%s]", everyDate)

		var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndDateAndSellDateNullOrderByTotalMarketValueDesc(accountName, everyDate)
		return real9OptimizeStockTransactionRecordArray
	}
}

// 查询可以加仓的股票
func (r *Real9StockTransactionRecordServiceImpl) getRealQuantStockTransactRecordArrayByAccountNameAndDateAndSellNull(accountName string, everyDate string) model.Real9QuantStockTransactionRecordArray {
	if properties.Real9Properties_.UseRealData == true {
		pIo.Infoln("查询可以加仓的股票，获取实时数据，日期[%s]", everyDate)

		// 根据账户名称，查询在real9_q_stock_transact_record表中，但不在real9_o_stock_transact_record表中未卖出的股票记录，不包括当天是最后一个交易日的股票
		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndSellNullAndNotInReal9OptimizeStockTransactionRecord(accountName, everyDate)
		if len(real9QuantStockTransactionRecordArray) == 0 {
			pIo.Infoln("日期为[%s]，账号[%s]没有可以加仓的股票", everyDate, accountName)
			return model.Real9QuantStockTransactionRecordArray{}
		}

		// 将code连接为字符串
		var codeArray []string
		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			codeArray = append(codeArray, real9QuantStockTransactionRecord.StockCode)
		}
		var codeString string = strings.Join(codeArray, ",")

		// 调用 Python 脚本
		cmd := exec.Command("python", properties.PythonProperties_.ManagePath, properties.PythonProperties_.PackageName, properties.PythonProperties_.FindRealCodeAndTotalMarketValueByCodeListMethodName, codeString)

		// 捕获标准输出
		var out bytes.Buffer
		cmd.Stdout = &out

		// 运行命令并处理错误
		if _error := cmd.Run(); _error != nil {
			pIo.Infoln("调用python程序，获取股票时报错：", _error)
			return model.Real9QuantStockTransactionRecordArray{}
		}

		// 解析返回的 JSON 数据
		var realStockTransactionDataAllArray []domain.RealStockTransactionDataAll
		if len(out.Bytes()) != 0 {
			reader := transform.NewReader(bytes.NewReader(out.Bytes()), simplifiedchinese.GBK.NewDecoder())
			all, err := ioutil.ReadAll(reader)
			if err != nil {
				pIo.Infoln("调用python程序，读取json数据时报错" + err.Error())
			}
			var result string = string(all)
			err = json.Unmarshal([]byte(result), &realStockTransactionDataAllArray)
			if err != nil {
				pIo.Infoln("调用python程序，转换json为struct数据时报错" + err.Error())
			}

			// 按照总市值升序排列
			if len(realStockTransactionDataAllArray) != 0 {
				var _real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = model.Real9QuantStockTransactionRecordArray{}
				n := len(realStockTransactionDataAllArray)
				for i := 0; i < n; i++ {
					for j := 0; j < n-i-1; j++ {
						if realStockTransactionDataAllArray[j].TotalMarketValue > realStockTransactionDataAllArray[j+1].TotalMarketValue {
							realStockTransactionDataAllArray[j], realStockTransactionDataAllArray[j+1] = realStockTransactionDataAllArray[j+1], realStockTransactionDataAllArray[j]
						}
					}
				}
				for _, realStockTransactionDataAll := range realStockTransactionDataAllArray {
					var real9QuantStockTransactionRecord model.Real9QuantStockTransactionRecord
					real9QuantStockTransactionRecord.StockCode = realStockTransactionDataAll.Code
					real9QuantStockTransactionRecord.AccountName = accountName
					var _real9QuantStockTransactionRecord model.Real9QuantStockTransactionRecord = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndStockCodeAndSellDateNull(accountName, real9QuantStockTransactionRecord.StockCode)
					real9QuantStockTransactionRecord.BuyPrice = _real9QuantStockTransactionRecord.BuyPrice
					real9QuantStockTransactionRecord.BuyAmount = _real9QuantStockTransactionRecord.BuyAmount
					real9QuantStockTransactionRecord.BuyDate = _real9QuantStockTransactionRecord.BuyDate
					_real9QuantStockTransactionRecordArray = append(_real9QuantStockTransactionRecordArray, &real9QuantStockTransactionRecord)
				}

				return _real9QuantStockTransactionRecordArray
			} else {
				pIo.Infoln("无法获取到股票的实时数据，无法加仓")
				return model.Real9QuantStockTransactionRecordArray{}
			}
		} else {
			pIo.Infoln("调用python程序，获取股票的数据为空")

			return model.Real9QuantStockTransactionRecordArray{}
		}
	} else {
		pIo.Infoln("查询可以加仓的股票，获取历史数据，日期[%s]", everyDate)

		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndDateAndSellDateNullAndNotInReal9OptimizeStockTransactionRecordOrderByTotalMarketValueDesc(accountName, everyDate)
		return real9QuantStockTransactionRecordArray
	}
}

/***************************************************************************** 恢复数据 *****************************************************************************/

// 将real9_q、real9_o开头的表，恢复为这一天的上一天的数据
func (r *Real9StockTransactionRecordServiceImpl) RestoreReal9(finalDate *string) {
	// 恢复real9_q_account表和real9_o_account表中上一轮的数据
	var previousDate *string = r._stockTransactionDataAllDaoImpl.FindLastDateByDate(*finalDate)
	r.restoreReal9QuantAccountByDate(*previousDate)
	r.restoreReal9OptimizeAccountByDate(*previousDate)

	// 恢复real9_q_account_log表和real9_o_account_log表中上一轮的数据
	r.restoreReal9QuantAccountLogByDate(*finalDate)
	r.restoreReal9OptimizeAccountLogByDate(*finalDate)

	// 恢复real9_q_stock_transact_record表和real9_o_stock_transact_record表中上一轮的数据
	r.restoreReal9QuantStockTransactionRecordByDate(*finalDate)
	r.restoreReal9OptimizeStockTransactionRecordByDate(*finalDate)
}

// 根据日期，恢复real9_q_account表中的数据
func (r *Real9StockTransactionRecordServiceImpl) restoreReal9QuantAccountByDate(date string) {
	pIo.Infoln("根据日期[%s]，恢复real9_q_account表中的数据", date)

	r._real9QuantAccountDaoImpl.TruncateTable()
	r._real9QuantAccountDaoImpl.InsertFromReal9QuantAccountLogByDate(date)
}

// 根据日期，恢复real9_o_account表中的数据
func (r *Real9StockTransactionRecordServiceImpl) restoreReal9OptimizeAccountByDate(date string) {
	pIo.Infoln("根据日期[%s]，恢复real9_o_account表中的数据", date)

	r._real9OptimizeAccountDaoImpl.TruncateTable()
	r._real9OptimizeAccountDaoImpl.InsertFromReal9OptimizeAccountLogByDate(date)
}

// 根据日期，恢复real9_q_account_log表中的数据
func (r *Real9StockTransactionRecordServiceImpl) restoreReal9QuantAccountLogByDate(date string) {
	pIo.Infoln("根据日期[%s]，恢复real9_q_account_log表中的数据", date)

	r._real9QuantAccountLogDaoImpl.DeleteByDate(date)
}

// 根据日期，恢复real9_o_account_log表中的数据
func (r *Real9StockTransactionRecordServiceImpl) restoreReal9OptimizeAccountLogByDate(date string) {
	pIo.Infoln("根据日期[%s]，恢复real9_o_account_log表中的数据", date)

	r._real9OptimizeAccountLogDaoImpl.DeleteByDate(date)
}

// 根据日期，恢复real9_q_stock_transact_record表中的数据
func (r *Real9StockTransactionRecordServiceImpl) restoreReal9QuantStockTransactionRecordByDate(date string) {
	pIo.Infoln("根据日期[%s]，恢复real9_q_stock_transact_record表中的数据", date)

	r._real9QuantStockTransactionRecordDaoImpl.DeleteBySellDateNullAndBuyDate(date)
	r._real9QuantStockTransactionRecordDaoImpl.UpdateNullBySellDate(date)
}

// 根据日期，恢复real9_o_stock_transact_record表中的数据
func (r *Real9StockTransactionRecordServiceImpl) restoreReal9OptimizeStockTransactionRecordByDate(date string) {
	pIo.Infoln("根据日期[%s]，恢复real9_o_stock_transact_record表中的数据", date)

	r._real9OptimizeStockTransactionRecordDaoImpl.DeleteBySellDateNullAndBuyDate(date)
	r._real9OptimizeStockTransactionRecordDaoImpl.UpdateNullBySellDate(date)
}

// 打印交易建议，并且发送邮件
func (r *Real9StockTransactionRecordServiceImpl) printAndMailSuggestion(date string) {
	pIo.Infoln("打印交易建议，并且发送邮件")

	// 建议
	var openOrCloseCommodityFutureSuggestion domain.OpenOrCloseCommodityFutureSuggestion = domain.OpenOrCloseCommodityFutureSuggestion{}

	// 按总资产排序的账号
	var totalAssetsOrderAccountNameArray [4]string

	// 按总资产顺序查询账号和持仓
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAllOrderByTotalAssetsDesc()
	var _real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = model.Real9OptimizeStockTransactionRecordArray{}
	if len(real9OptimizeAccountArray) > 0 {
		for i, real9OptimizeAccount := range real9OptimizeAccountArray {
			var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(real9OptimizeAccount.AccountName)
			if len(real9OptimizeStockTransactionRecordArray) > 0 {
				for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
					_real9OptimizeStockTransactionRecordArray = append(_real9OptimizeStockTransactionRecordArray, real9OptimizeStockTransactionRecord)
				}
				openOrCloseCommodityFutureSuggestion.Real9OptimizeStockTransactionRecordArray = _real9OptimizeStockTransactionRecordArray
			}
			totalAssetsOrderAccountNameArray[i] = real9OptimizeAccount.AccountName
		}
		openOrCloseCommodityFutureSuggestion.TotalAssetsOrderAccountNameArray = totalAssetsOrderAccountNameArray
	}

	// 查询总资产最多的账号当天买入和卖出的记录
	var currentDateBuyStockArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndDateAndSellNull(real9OptimizeAccountArray[0].AccountName, date)
	var currentDateSellStockArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndDateAndSellNotNull(real9OptimizeAccountArray[0].AccountName, date)
	openOrCloseCommodityFutureSuggestion.CurrentDateBuyStockArray = currentDateBuyStockArray
	openOrCloseCommodityFutureSuggestion.CurrentDateSellStockArray = currentDateSellStockArray

	// 打印买卖建议
	data, _ := json.MarshalIndent(&_real9OptimizeStockTransactionRecordArray, "", "\t")
	pIo.Infoln("交易建议：" + string(data))

	// 解析邮件模板
	tmpl, _ := template.ParseFiles("internal/template/email/open_or_close_commodity_future_suggestion.html")
	body := new(bytes.Buffer)
	tmpl.Execute(body, openOrCloseCommodityFutureSuggestion)

	// 发送邮件
	e := email.NewEmail()
	//设置发送方的邮箱
	e.From = properties.Real9Properties_.EmailFrom
	// 设置接收方的邮箱
	e.To = []string{properties.Real9Properties_.EmailTo}
	//设置主题
	e.Subject = properties.Real9Properties_.EmailSubject
	//设置文件发送的内容
	e.Text = body.Bytes()
	//设置服务器相关的配置
	err := e.Send(properties.Real9Properties_.EmailAddress, smtp.PlainAuth("", properties.Real9Properties_.EmailUsername, properties.Real9Properties_.EmailPassword, properties.Real9Properties_.EmailHost))
	if err != nil {
		pIo.Infoln("发送邮件失败，重新发送。" + err.Error())
		r.printAndMailSuggestion(date)
	}
}

/******************************************************************* 比对方法 *******************************************************************/

// 比对quant_*和real9_q_*表、optimize_*和real9_o_*表，如果有不一致，则退出程序
func (r *Real9StockTransactionRecordServiceImpl) compareQuantAndOptimizeWithReal9QuantAndReal9Optimize(everyDate string) {
	if properties.Real9Properties_.UseRealData == false && properties.Real9Properties_.Compare == true {
		pIo.Infoln("比对quant_*和real9_q_*表、optimize_*和real9_o_*表，如果有不一致，则退出程序")

		// 比对quant_*和real9_q_*表
		var quantAccountLogArray model.QuantAccountLogArray = r._quantAccountLogDaoImpl.FindByBeginDateAndEndDateOrderByDateAndAccountName(everyDate, everyDate)
		var real9QuantAccountLogArray model.Real9QuantAccountLogArray = r._real9QuantAccountLogDaoImpl.FindByDate(everyDate)

		if len(quantAccountLogArray) > 0 && len(real9QuantAccountLogArray) > 0 {
			for _, quantAccountLog := range quantAccountLogArray {
				for _, real9QuantAccountLog := range real9QuantAccountLogArray {
					if quantAccountLog.AccountName == real9QuantAccountLog.AccountName {
						// 判断stock_assets是否一致
						var quantAccountLogStockAssets float64 = math.Floor(quantAccountLog.StockAssets*10) / 10
						var real9QuantAccountLogStockAssets float64 = math.Floor(real9QuantAccountLog.StockAssets*10) / 10
						if quantAccountLogStockAssets != real9QuantAccountLogStockAssets {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的stock_assets列为[%f]，real9_q_account_log表的[%s]账号的stock_assets列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.StockAssets, real9QuantAccountLog.AccountName, real9QuantAccountLog.StockAssets)
							os.Exit(0)
						}
						// 判断capital_assets是否一致
						var quantAccountLogCapitalAssets float64 = math.Floor(quantAccountLog.CapitalAssets*10) / 10
						var real9QuantAccountLogCapitalAssets float64 = math.Floor(real9QuantAccountLog.CapitalAssets*10) / 10
						if quantAccountLogCapitalAssets != real9QuantAccountLogCapitalAssets {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的capital_assets列为[%f]，real9_q_account_log表的[%s]账号的capital_assets列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.CapitalAssets, real9QuantAccountLog.AccountName, real9QuantAccountLog.CapitalAssets)
							os.Exit(0)
						}
						// 判断total_assets是否一致
						var quantAccountLogTotalAssets float64 = math.Floor(quantAccountLog.TotalAssets*10) / 10
						var real9QuantAccountLogTotalAssets float64 = math.Floor(real9QuantAccountLog.TotalAssets*10) / 10
						if quantAccountLogTotalAssets != real9QuantAccountLogTotalAssets {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的total_assets列为[%f]，real9_q_account_log表的[%s]账号的total_assets列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.TotalAssets, real9QuantAccountLog.AccountName, real9QuantAccountLog.TotalAssets)
							os.Exit(0)
						}
						// 判断total_stamp_duty是否一致
						var quantAccountLogTotalStampDuty float64 = math.Floor(quantAccountLog.TotalStampDuty*10) / 10
						var real9QuantAccountLogTotalStampDuty float64 = math.Floor(real9QuantAccountLog.TotalStampDuty*10) / 10
						if quantAccountLogTotalStampDuty != real9QuantAccountLogTotalStampDuty {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的total_stamp_duty列为[%f]，real9_q_account_log表的[%s]账号的total_stamp_duty列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.TotalStampDuty, real9QuantAccountLog.AccountName, real9QuantAccountLog.TotalStampDuty)
							os.Exit(0)
						}
						// 判断total_registrate_fee_when_buy是否一致
						var quantAccountLogTotalRegistrateFeeWhenBuy float64 = math.Floor(quantAccountLog.TotalRegistrateFeeWhenBuy*10) / 10
						var real9QuantAccountLogTotalRegistrateFeeWhenBuy float64 = math.Floor(real9QuantAccountLog.TotalRegistrateFeeWhenBuy*10) / 10
						if quantAccountLogTotalRegistrateFeeWhenBuy != real9QuantAccountLogTotalRegistrateFeeWhenBuy {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的total_registrate_fee_when_buy列为[%f]，real9_q_account_log表的[%s]账号的total_registrate_fee_when_buy列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.TotalRegistrateFeeWhenBuy, real9QuantAccountLog.AccountName, real9QuantAccountLog.TotalRegistrateFeeWhenBuy)
							os.Exit(0)
						}
						// 判断total_commission_when_buy是否一致
						var quantAccountLogTotalCommissionWhenBuy float64 = math.Floor(quantAccountLog.TotalCommissionWhenBuy*10) / 10
						var real9QuantAccountLogTotalCommissionWhenBuy float64 = math.Floor(real9QuantAccountLog.TotalCommissionWhenBuy*10) / 10
						if quantAccountLogTotalCommissionWhenBuy != real9QuantAccountLogTotalCommissionWhenBuy {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的total_commission_when_buy列为[%f]，real9_q_account_log表的[%s]账号的total_commission_when_buy列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.TotalCommissionWhenBuy, real9QuantAccountLog.AccountName, real9QuantAccountLog.TotalCommissionWhenBuy)
							os.Exit(0)
						}
						// 判断total_registrate_fee_when_sell是否一致
						var quantAccountLogTotalRegistrateFeeWhenSell float64 = math.Floor(quantAccountLog.TotalRegistrateFeeWhenSell*10) / 10
						var real9QuantAccountLogTotalRegistrateFeeWhenSell float64 = math.Floor(real9QuantAccountLog.TotalRegistrateFeeWhenSell*10) / 10
						if quantAccountLogTotalRegistrateFeeWhenSell != real9QuantAccountLogTotalRegistrateFeeWhenSell {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的total_registrate_fee_when_sell列为[%f]，real9_q_account_log表的[%s]账号的total_registrate_fee_when_sell列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.TotalRegistrateFeeWhenSell, real9QuantAccountLog.AccountName, real9QuantAccountLog.TotalRegistrateFeeWhenSell)
							os.Exit(0)
						}
						// 判断total_commission_when_sell是否一致
						var quantAccountLogTotalCommissionWhenSell float64 = math.Floor(quantAccountLog.TotalCommissionWhenSell*10) / 10
						var real9QuantAccountLogTotalCommissionWhenSell float64 = math.Floor(real9QuantAccountLog.TotalCommissionWhenSell*10) / 10
						if quantAccountLogTotalCommissionWhenSell != real9QuantAccountLogTotalCommissionWhenSell {
							pIo.Fatalf("日期[%s]，quant_account_log表的[%s]账号的total_commission_when_sell列为[%f]，real9_q_account_log表的[%s]账号的total_commission_when_sell列为[%f]，它们不一致",
								everyDate, quantAccountLog.AccountName, quantAccountLog.TotalCommissionWhenSell, real9QuantAccountLog.AccountName, real9QuantAccountLog.TotalCommissionWhenSell)
							os.Exit(0)
						}
					}
				}
			}
		} else {
			pIo.Infoln("quant_*或real9_q_*表中没有[%s]的记录，不再做比对", everyDate)
		}

		// 比对optimize_*和real9_o_*表
		var optimizeAccountLogArray model.OptimizeAccountLogArray = r._optimizeAccountLogDaoImpl.FindByBeginDateAndEndDateOrderByDateAndAccountName(everyDate, everyDate)
		var real9OptimizeAccountLogArray model.Real9OptimizeAccountLogArray = r._real9OptimizeAccountLogDaoImpl.FindByDate(everyDate)

		if len(optimizeAccountLogArray) > 0 && len(real9OptimizeAccountLogArray) > 0 {
			for _, optimizeAccountLog := range optimizeAccountLogArray {
				for _, real9OptimizeAccountLog := range real9OptimizeAccountLogArray {
					if optimizeAccountLog.AccountName == real9OptimizeAccountLog.AccountName {
						// 判断stock_assets是否一致
						var optimizeAccountLogStockAssets float64 = math.Floor(optimizeAccountLog.StockAssets*10) / 10
						var real9OptimizeAccountLogStockAssets float64 = math.Floor(real9OptimizeAccountLog.StockAssets*10) / 10
						if optimizeAccountLogStockAssets != real9OptimizeAccountLogStockAssets {
							pIo.Fatalf("日期[%s]，optimize_account_log表的[%s]账号的stock_assets列为[%f]，real9_o_account_log表的[%s]账号的stock_assets列为[%f]，它们不一致",
								everyDate, optimizeAccountLog.AccountName, optimizeAccountLog.StockAssets, real9OptimizeAccountLog.AccountName, real9OptimizeAccountLog.StockAssets)
							os.Exit(0)
						}
						// 判断capital_assets是否一致
						var optimizeAccountLogCapitalAssets float64 = math.Floor(optimizeAccountLog.CapitalAssets*10) / 10
						var real9OptimizeAccountLogCapitalAssets float64 = math.Floor(real9OptimizeAccountLog.CapitalAssets*10) / 10
						if optimizeAccountLogCapitalAssets != real9OptimizeAccountLogCapitalAssets {
							pIo.Fatalf("日期[%s]，optimize_account_log表的[%s]账号的capital_assets列为[%f]，real9_o_account_log表的[%s]账号的capital_assets列为[%f]，它们不一致",
								everyDate, optimizeAccountLog.AccountName, optimizeAccountLog.CapitalAssets, real9OptimizeAccountLog.AccountName, real9OptimizeAccountLog.CapitalAssets)
							os.Exit(0)
						}
						// 判断total_assets是否一致
						var optimizeAccountLogTotalAssets float64 = math.Floor(optimizeAccountLog.TotalAssets*10) / 10
						var real9OptimizeAccountLogTotalAssets float64 = math.Floor(real9OptimizeAccountLog.TotalAssets*10) / 10
						if optimizeAccountLogTotalAssets != real9OptimizeAccountLogTotalAssets {
							pIo.Fatalf("日期[%s]，optimize_account_log表的[%s]账号的total_assets列为[%f]，real9_o_account_log表的[%s]账号的total_assets列为[%f]，它们不一致",
								everyDate, optimizeAccountLog.AccountName, optimizeAccountLog.TotalAssets, real9OptimizeAccountLog.AccountName, real9OptimizeAccountLog.TotalAssets)
							os.Exit(0)
						}
						// 判断total_stamp_duty是否一致
						var optimizeAccountLogTotalStampDuty float64 = math.Floor(optimizeAccountLog.TotalStampDuty*10) / 10
						var real9OptimizeAccountLogTotalStampDuty float64 = math.Floor(real9OptimizeAccountLog.TotalStampDuty*10) / 10
						if optimizeAccountLogTotalStampDuty != real9OptimizeAccountLogTotalStampDuty {
							pIo.Fatalf("日期[%s]，optimize_account_log表的[%s]账号的total_stamp_duty列为[%f]，real9_o_account_log表的[%s]账号的total_stamp_duty列为[%f]，它们不一致",
								everyDate, optimizeAccountLog.AccountName, optimizeAccountLog.TotalStampDuty, real9OptimizeAccountLog.AccountName, real9OptimizeAccountLog.TotalStampDuty)
							os.Exit(0)
						}
						// 判断total_registrate_fee_when_buy是否一致
						var optimizeAccountLogTotalRegistrateFeeWhenBuy float64 = math.Floor(optimizeAccountLog.TotalRegistrateFeeWhenBuy*10) / 10
						var real9OptimizeAccountLogTotalRegistrateFeeWhenBuy float64 = math.Floor(real9OptimizeAccountLog.TotalRegistrateFeeWhenBuy*10) / 10
						if optimizeAccountLogTotalRegistrateFeeWhenBuy != real9OptimizeAccountLogTotalRegistrateFeeWhenBuy {
							pIo.Fatalf("日期[%s]，optimize_account_log表的[%s]账号的total_registrate_when_buy列为[%f]，real9_o_account_log表的[%s]账号的total_registrate_when_buy列为[%f]，它们不一致",
								everyDate, optimizeAccountLog.AccountName, optimizeAccountLog.TotalRegistrateFeeWhenBuy, real9OptimizeAccountLog.AccountName, real9OptimizeAccountLog.TotalRegistrateFeeWhenBuy)
							os.Exit(0)
						}
						// 判断total_commission_when_buy是否一致
						var optimizeAccountLogTotalCommissionWhenBuy float64 = math.Floor(optimizeAccountLog.TotalCommissionWhenBuy*10) / 10
						var real9OptimizeAccountLogTotalCommissionWhenBuy float64 = math.Floor(real9OptimizeAccountLog.TotalCommissionWhenBuy*10) / 10
						if optimizeAccountLogTotalCommissionWhenBuy != real9OptimizeAccountLogTotalCommissionWhenBuy {
							pIo.Fatalf("日期[%s]，optimize_account_log表的[%s]账号的total_commission_when_buy列为[%f]，real9_o_account_log表的[%s]账号的total_commission_when_buy列为[%f]，它们不一致",
								everyDate, optimizeAccountLog.AccountName, optimizeAccountLog.TotalCommissionWhenBuy, real9OptimizeAccountLog.AccountName, real9OptimizeAccountLog.TotalCommissionWhenBuy)
							os.Exit(0)
						}
						// 判断total_registrate_fee_when_sell是否一致
						var optimizeAccountLogTotalRegistrateFeeWhenSell float64 = math.Floor(optimizeAccountLog.TotalRegistrateFeeWhenSell*10) / 10
						var real9OptimizeAccountLogTotalRegistrateFeeWhenSell float64 = math.Floor(real9OptimizeAccountLog.TotalRegistrateFeeWhenSell*10) / 10
						if optimizeAccountLogTotalRegistrateFeeWhenSell != real9OptimizeAccountLogTotalRegistrateFeeWhenSell {
							pIo.Fatalf("日期[%s]，optimize_account_log表的[%s]账号的total_registrate_fee_when_sell列为[%f]，real9_o_account_log表的[%s]账号的total_registrate_fee_when_sell列为[%f]，它们不一致",
								everyDate, optimizeAccountLog.AccountName, optimizeAccountLog.TotalRegistrateFeeWhenSell, real9OptimizeAccountLog.AccountName, real9OptimizeAccountLog.TotalRegistrateFeeWhenSell)
							os.Exit(0)
						}
					}
				}
			}
		} else {
			pIo.Infoln("optimize_*或real9_o_*表中没有[%s]的记录，不再做比对", everyDate)
		}
	}
}

/***************************************************************************** 量化方法 *****************************************************************************/

// 卖出之前更新real9_q_account
func (r *Real9StockTransactionRecordServiceImpl) updateQuantAccountBeforeSell(everyDate string) {
	pIo.Infoln("在卖出之前更新real9_q_account")

	// 返回实盘账户
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	for _, real9QuantAccount := range real9QuantAccountArray {
		// 股票资产
		var stockAssets float64 = 0

		// 计算每一个实盘账户，在某一天卖股票前的收益
		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(real9QuantAccount.AccountName)

		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			// 收盘价
			var currentClosePrice float64 = r.getRealOrHistoryClosePriceByByCodeAndDate(real9QuantStockTransactionRecord.StockCode, everyDate)
			// 注意：如果没有查询到数据的话，则golang的float64类型数据默认是0
			if currentClosePrice == 0 {
				// 说明股票在这一天没有交易记录
				pIo.Infoln("股票[%s]在日期[%s]没有交易记录，开始查找前一个交易日的记录", real9QuantStockTransactionRecord.StockCode, everyDate)

				// 如果在某一天没有开盘价，比如停牌，则查找最近一个交易日的开盘价
				currentClosePrice = r._stockTransactionDataAllDaoImpl.FindLastClosePriceByByCodeAndDate(real9QuantStockTransactionRecord.StockCode, everyDate)
			}

			// 计算这只股票的资产
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(real9QuantStockTransactionRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
		}

		// 更新real9_q_account表的hold_stock_number、stock_assets、total_assets字段
		if stockAssets != 0 {
			r._real9QuantAccountDaoImpl.UpdateBeforeSell(len(real9QuantStockTransactionRecordArray), stockAssets, real9QuantAccount.AccountName)
		}
	}
}

// 准备数据
func (r *Real9StockTransactionRecordServiceImpl) prepareData(statisticsDate string) {
	pIo.Infoln("准备数据：清空real9_q_stock_filter表，从stock_transaction_data_all表中向real9_q_stock_filter表中插入记录，按照total_market_value升序排列，包括正在持有的股票")

	// 清空real9_q_stock_filter表
	r._real9QuantStockFilterDaoImpl.TruncateTable()

	// 从stock_transaction_data_all表中向real9_q_stock_filter表中插入记录，按照total_market_value升序排列，包括正在持有的股票
	r._real9QuantStockFilterDaoImpl.InsertIntoReal9QuantStockFilterFromStockTransactionData(statisticsDate)
}

// 删除总市值不满足要求的股票
func (r *Real9StockTransactionRecordServiceImpl) deleteByTotalMarketValue(statisticsDate string) {
	pIo.Infoln("删除总市值不满足要求的股票，统计日[%s]", statisticsDate)

	var marketValueMainBoardBottomLimit float64 = properties.Real9Properties_.MarketValueMainBoardBottomLimit
	var marketValueCyBBoardBottomLimit float64 = properties.Real9Properties_.MarketValueCyBBoardBottomLimit

	// 过滤器：删除总市值不满足要求的股票
	r._real9QuantStockFilterDaoImpl.DeleteByTotalMarketValueBottomLimit(statisticsDate, marketValueMainBoardBottomLimit, marketValueCyBBoardBottomLimit)
}

// 只保留总市值最小的(10*账号数量+4)只股票
func (r *Real9StockTransactionRecordServiceImpl) retainMinTotalMarketValue() {
	pIo.Infoln("只保留总市值最小的(10*账号数量+4)只股票")

	var maxHoldStockNumber int = properties.Real9Properties_.MaxHoldStockNumber

	r._real9QuantStockFilterDaoImpl.RetainMinTotalMarketValue(maxHoldStockNumber)
}

// 去除一字涨停版
func (r *Real9StockTransactionRecordServiceImpl) deleteOneWordLimitUp(buyOrSelDate string) {
	pIo.Infoln("去除一字涨停版")

	var real9QuantStockFilterArray model.Real9QuantStockFilterArray = r._real9QuantStockFilterDaoImpl.FindAll()

	for _, real9QuantStockFilter := range real9QuantStockFilterArray {
		var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockFilter.StockCode, buyOrSelDate)

		// 如果当天停牌、退市、摘牌，则删除这只股票
		if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
			r._real9QuantStockFilterDaoImpl.DeleteByStockCode(real9QuantStockFilter.StockCode)
			continue
		}

		// 如果是一字涨停板，则删除
		if iUitl.OneWordLimitUp(stockTransactionDataAll, buyOrSelDate) {
			r._real9QuantStockFilterDaoImpl.DeleteByStockCode(real9QuantStockFilter.StockCode)
		}
	}
}

// 删除开盘价不满足要求的股票
func (r *Real9StockTransactionRecordServiceImpl) deleteOpenPriceBottomLimit(buyOrSelDate string) {
	pIo.Infoln("删除开盘价不满足要求的股票")

	var real9QuantStockFilterArray model.Real9QuantStockFilterArray = r._real9QuantStockFilterDaoImpl.FindAll()

	for _, real9QuantStockFilter := range real9QuantStockFilterArray {
		var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockFilter.StockCode, buyOrSelDate)

		// 如果当天停牌、退市、摘牌，则删除这只股票
		if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
			r._real9QuantStockFilterDaoImpl.DeleteByStockCode(real9QuantStockFilter.StockCode)
			continue
		}

		// 如果开盘价不满足要求，则删除
		if stockTransactionDataAll.OpenPrice < properties.Real9Properties_.OpenPriceBottomLimit {
			r._real9QuantStockFilterDaoImpl.DeleteByStockCode(real9QuantStockFilter.StockCode)
		}
	}
}

// 解决之前卖出失败的情况
func (r *Real9StockTransactionRecordServiceImpl) sellQuantResolveFail(everyDate string) {
	pIo.Infoln("解决之前卖出失败的情况")

	// real9_quant_optimize_account表的所有记录
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	for _, real9QuantAccount := range real9QuantAccountArray {
		// 如果这个账户没有持有股票，则查找下一个账户
		if real9QuantAccount.HoldStockNumber == 0 {
			pIo.Infoln("账号[%s]持股票数量为0，不需要卖出股票", (*real9QuantAccount).AccountName)
			continue
		}

		// 查询某个量化账户之前卖出失败的股票
		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindQuantResolveFailSellByAccountName(real9QuantAccount.AccountName)

		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			// 查询股票
			var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockTransactionRecord.StockCode, everyDate)

			// 如果没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录
			if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
				pIo.Infoln("股票[%s]在日期[%s]没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录", real9QuantStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 如果是一字跌停板，因此跳过这条记录
			if iUitl.OneWordLimitDown(stockTransactionDataAll, everyDate) {
				pIo.Infoln("股票[%s]在日期[%s]是一字跌停板，因此跳过这条记录", real9QuantStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 卖出
			r._real9QuantStockTransactionRecordDaoImpl.UpdateWhenSell(everyDate, stockTransactionDataAll, *real9QuantStockTransactionRecord)
		}
	}
}

// 退市卖出
func (r *Real9StockTransactionRecordServiceImpl) sellQuantDelist(everyDate string) {
	pIo.Infoln("退市卖出")

	// real9_q_account表的所有记录
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	for _, realQuantAccount := range real9QuantAccountArray {
		// 如果这个账户没有持有股票，则查找下一个账户
		if realQuantAccount.HoldStockNumber == 0 {
			pIo.Infoln("账号[%s]持股票数量为0，不需要卖出股票", (*realQuantAccount).AccountName)
			continue
		}

		// 查询某个账号是否有退市的股票，如果有则卖出
		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindDelistByLastTransactionDateAndAccountName(everyDate, realQuantAccount.AccountName)

		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			// 查询股票
			var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockTransactionRecord.StockCode, everyDate)

			// 由于这个是停牌、退市、摘牌的股票，因此一定要卖掉
			if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
				stockTransactionDataAll = r._stockTransactionDataAllDaoImpl.FindLastStockTransactionDataAllClosePriceByByCodeAndDate(real9QuantStockTransactionRecord.StockCode, everyDate)
				pIo.Infoln("股票[%s]在日期[%s]停牌、退市、摘牌，因此强行卖掉这只股票", real9QuantStockTransactionRecord.StockCode, everyDate)
			}

			// 卖出
			r._real9QuantStockTransactionRecordDaoImpl.UpdateWhenSell(everyDate, stockTransactionDataAll, *real9QuantStockTransactionRecord)
		}
	}
}

// 卖出
func (r *Real9StockTransactionRecordServiceImpl) doQuantSell(everyDate string) {
	pIo.Infoln("卖出")

	// real9_q_account表的所有记录
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	for _, real9QuantAccount := range real9QuantAccountArray {
		// 如果这个账户没有持有股票，则查找下一个账户
		if real9QuantAccount.HoldStockNumber == 0 {
			pIo.Infoln("账号[%s]持股票数量为0，不需要卖出股票", (*real9QuantAccount).AccountName)
			continue
		}

		// 某个量化账户的买入的股票的交易记录，不包括real9_q_stock_filter表中已经存在的记录
		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndNotInReal9QuantStockFilter(real9QuantAccount.AccountName)

		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			// 查询股票
			var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockTransactionRecord.StockCode, everyDate)

			// 如果没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录
			if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
				r._real9QuantStockTransactionRecordDaoImpl.UpdateFailSellReasonById(real9QuantStockTransactionRecord.ID, constants.SUSPENSION)
				pIo.Infoln("股票[%s]在日期[%s]没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录", real9QuantStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 如果是一字跌停板，因此跳过这条记录
			if iUitl.OneWordLimitDown(stockTransactionDataAll, everyDate) {
				r._real9QuantStockTransactionRecordDaoImpl.UpdateFailSellReasonById(real9QuantStockTransactionRecord.ID, constants.LIMIT_DOWN)
				pIo.Infoln("股票[%s]在日期[%s]是一字跌停板，因此跳过这条记录", real9QuantStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 卖出
			r._real9QuantStockTransactionRecordDaoImpl.UpdateWhenSell(everyDate, stockTransactionDataAll, *real9QuantStockTransactionRecord)
		}
	}
}

// 在卖出之后更新real9_q_account
func (r *Real9StockTransactionRecordServiceImpl) updateQuantAccountAfterSell(everyDate string) {
	pIo.Infoln("在卖出之后更新real9_q_account")

	// 返回实盘量化账户
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	for _, real9QuantAccount := range real9QuantAccountArray {
		// 总资产
		var stockAssets float64 = 0
		// 持股数量
		var sellOrBuyStockNumber int = 0

		// 计算每一个量化账户，在某一天卖完股票后持有股票的资产
		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(real9QuantAccount.AccountName)

		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			// 查找某只股票在某一天的开盘价
			var currentOpenPrice float64 = r.getRealOrHistoryOpenPriceByByCodeAndDate(real9QuantStockTransactionRecord.StockCode, everyDate)

			if currentOpenPrice == 0 {
				// 如果在某一天没有开盘价，比如停牌，则查找最近一个交易日的开盘价
				currentOpenPrice = r._stockTransactionDataAllDaoImpl.FindLastOpenPriceByByCodeAndDate(real9QuantStockTransactionRecord.StockCode, everyDate)
			}

			// 卖完股票后的股票资产、持股数量
			decimalValue := decimal.NewFromFloat(currentOpenPrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(real9QuantStockTransactionRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
			sellOrBuyStockNumber = sellOrBuyStockNumber + 1
		}

		// 计算每一个量化账户，在某一天卖完股票后卖出股票的资产
		//var _real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndDateAndSellNotNull(real9QuantAccount.AccountName, everyDate)
		//for _, _real9QuantStockTransactionRecord := range _real9QuantStockTransactionRecordArray {
		//	// 查找某只股票在某一天的开盘价
		//	var currentOpenPrice float64 = r._stockTransactionDataAllDaoImpl.getRealOrHistoryOpenPriceByByCodeAndDate(_real9QuantStockTransactionRecord.StockCode, everyDate)
		//
		//	if currentOpenPrice == 0 {
		//		// 如果在某一天没有开盘价，比如停牌，则查找最近一个交易日的开盘价
		//		currentOpenPrice = r._stockTransactionDataAllDaoImpl.FindLastOpenPriceByByCodeAndDate(_real9QuantStockTransactionRecord.StockCode, everyDate)
		//	}
		//
		//	// 卖完股票后卖出股票的资产
		//	sellStockAssets = sellStockAssets + int(currentOpenPrice*float64(_real9QuantStockTransactionRecord.BuyAmount))
		//}

		// 更新optimize_account表
		r._real9QuantAccountDaoImpl.UpdateAfterSell(sellOrBuyStockNumber, stockAssets, *real9QuantAccount)
	}
}

// 买入
func (r *Real9StockTransactionRecordServiceImpl) doQuantBuy(everyDate string) {
	pIo.Infoln("买入")

	// 查询real9_q_account表的记录
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	if real9QuantAccountArray != nil && len(real9QuantAccountArray) > 0 {
		for _, real9QuantAccount := range real9QuantAccountArray {

			var holdStockNumber int = real9QuantAccount.HoldStockNumber
			// 如果某个账号的持股数量已经到达最大持股数量，则跳过这个账号
			if holdStockNumber >= properties.Real9Properties_.MaxHoldStockNumber {
				pIo.Infoln("账号[%s]的持股数量已经到达[%d]只，不再买入股票", real9QuantAccount.AccountName, holdStockNumber)
				continue
			}

			// 查询real9_q_stock_filter表的记录，不包括real9_q_stock_transact_record表中还没有卖出的记录
			var real9QuantStockFilterArray model.Real9QuantStockFilterArray = r._real9QuantStockFilterDaoImpl.FindByStockCodeNotInAndReal9QuantStockTransactionRecordAndDateNull(everyDate)

			if real9QuantStockFilterArray != nil && len(real9QuantStockFilterArray) > 0 {
				for _, real9QuantStockFilter := range real9QuantStockFilterArray {

					// 查询股票记录
					var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockFilter.StockCode, everyDate)
					if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
						pIo.Infoln("股票在日期[%s]没有交易记录，可能是停牌、退市、摘牌，从表quant_stock_filter表中删除这条记录，跳过这只股票", everyDate)

						// 从real9_q_stock_filter表中删除这条记录
						r._real9QuantStockFilterDaoImpl.DeleteByStockCode(real9QuantStockFilter.StockCode)

						continue
					}

					// 如果股票的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个机器人
					if iUitl.CalculateBuyStockFee(real9QuantStockFilter.StockCode, stockTransactionDataAll.OpenPrice, 100) > float64(real9QuantAccount.CapitalAssets) {
						break
					}

					// 如果可以买，则向real9_q_stock_transact_record表中插入数据，从real9_q_stock_filter表中删除这条记录。
					// 计算应该买入股票的数量
					// real9_q_stock_filter表的记录数
					var real9QuantStockFilterNumber int = r._real9QuantStockFilterDaoImpl.Count()

					// 应当买入的股票的数量
					var shouldBuyStockNumber int = -1
					if real9QuantStockFilterNumber <= (properties.Real9Properties_.MaxHoldStockNumber - real9QuantAccount.HoldStockNumber) {
						shouldBuyStockNumber = real9QuantStockFilterNumber
					} else {
						shouldBuyStockNumber = properties.Real9Properties_.MaxHoldStockNumber - real9QuantAccount.HoldStockNumber
					}

					// 判断是否需要继续买入
					if shouldBuyStockNumber == 0 {
						pIo.Infoln("账号[%s]持股数量已经是%d，不再需要买入股票", real9QuantAccount.AccountName, properties.Real9Properties_.MaxHoldStockNumber)
						break
					}

					// 计算买多少股
					// 买入多少股
					var buyOrSellAmount int = 100

					for real9QuantAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9QuantAccount.HoldStockNumber) >= iUitl.CalculateBuyStockFee(real9QuantStockFilter.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) {
						if iUitl.CalculateBuyStockFee(real9QuantStockFilter.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) >= real9QuantAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9QuantAccount.HoldStockNumber) {
							break
						}
						buyOrSellAmount = buyOrSellAmount + 100
					}
					if real9QuantAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9QuantAccount.HoldStockNumber) < iUitl.CalculateBuyStockFee(real9QuantStockFilter.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) {
						if buyOrSellAmount == 100 {
							// 从real9_q_stock_filter表中删除这条记录
							r._real9QuantStockFilterDaoImpl.DeleteByStockCode(real9QuantStockFilter.StockCode)

							continue
						} else {
							buyOrSellAmount = buyOrSellAmount - 100
						}
					}

					// 向表real9_q_stock_transact_record中插入记录
					r._real9QuantStockFilterDaoImpl.Insert(real9QuantAccount.AccountName, real9QuantStockFilter.StockCode, everyDate,
						stockTransactionDataAll.OpenPrice, buyOrSellAmount,
						iUitl.CalculateRegistrationFee(real9QuantStockFilter.StockCode, buyOrSellAmount),
						iUitl.CalculateCommission(stockTransactionDataAll.OpenPrice, buyOrSellAmount))

					// 删除real9_q_stock_filter表中的记录
					r._real9QuantStockFilterDaoImpl.DeleteByStockCode(real9QuantStockFilter.StockCode)

					// 更新账号的持股数量
					holdStockNumber = holdStockNumber + 1

					// 如果某个账号的持股数量已经到达最大持股数量，则跳过这个账号
					if holdStockNumber >= properties.Real9Properties_.MaxHoldStockNumber {
						pIo.Infoln("账号[%s]的持股数量已经到达[%d]只，不再买入股票", real9QuantAccount.AccountName, holdStockNumber)
						break
					}
				}
			} else {
				pIo.Infoln("表real9_q_account中没有记录，不再买入股票")
			}
		}
	} else {
		pIo.Infoln("表real9_q_account中没有记录")
	}
}

// 在买入之后更新real9_q_account
func (r *Real9StockTransactionRecordServiceImpl) updateQuantAccountAfterBuy(everyDate string) {
	pIo.Infoln("在买入之后更新real9_q_account")

	// 返回量化账户
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	for _, real9QuantAccount := range real9QuantAccountArray {

		// 股票资产
		var stockAssets float64 = 0
		// 当天买入的股票资产
		var currentBuyOrSellStockAssets float64 = 0
		// 买入股票的数量
		var sellOrBuyStockNumber int = 0

		// 计算每一个量化账户，在某一天买完股票后的收益
		var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(real9QuantAccount.AccountName)
		// 如果没有买股票，则直接将quant_account表中的记录插入到quant_account_log表中
		if real9QuantStockTransactionRecordArray == nil || len(real9QuantStockTransactionRecordArray) == 0 {
			// 向表quant_account_log中插入数据
			//u.db.Exec("insert into quant_account_log(DATE_, ACCOUNT_NAME, HOLD_STOCK_NUMBER, STOCK_ASSETS, "+
			//	"CAPITAL_ASSETS, TOTAL_ASSETS, TOTAL_STAMP_DUTY, TOTAL_REGISTRATE_FEE_WHEN_BUY, TOTAL_COMMISSION_WHEN_BUY, "+
			//	"TOTAL_REGISTRATE_FEE_WHEN_SELL, TOTAL_COMMISSION_WHEN_SELL) "+
			//	"select to_date(?, 'yyyy-mm-dd'), t.ACCOUNT_NAME, t.HOLD_STOCK_NUMBER, t.STOCK_ASSETS, t.CAPITAL_ASSETS, t.TOTAL_ASSETS, t.TOTAL_STAMP_DUTY, "+
			//	"t.TOTAL_REGISTRATE_FEE_WHEN_BUY, t.TOTAL_COMMISSION_WHEN_BUY, t.TOTAL_REGISTRATE_FEE_WHEN_SELL, t.TOTAL_COMMISSION_WHEN_SELL "+
			//	"from quant_account t where t.account_name = ?",
			//	transactionDate, (*quantAccount).AccountName)

			continue
		}

		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			// 查找某只股票在某一天的收盘价
			// 股票的收盘价
			var currentClosePrice float64 = r.getRealOrHistoryClosePriceByByCodeAndDate(real9QuantStockTransactionRecord.StockCode, everyDate)
			// 注意：如果没有查询到数据的话，则golang的float64类型数据默认是0
			if currentClosePrice == 0 {
				// 说明股票在这一天没有交易记录
				pIo.Infoln("股票[%s]在日期[%s]没有交易记录，可能是停牌，开始查找前一个交易日的记录", real9QuantStockTransactionRecord.StockCode, everyDate)

				// 如果在某一天没有收盘价，比如停牌，则查找最近一个交易日的收盘价
				currentClosePrice = r._stockTransactionDataAllDaoImpl.FindLastClosePriceByByCodeAndDate(real9QuantStockTransactionRecord.StockCode, everyDate)
			}

			// 买入股票后的收益
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(real9QuantStockTransactionRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
			sellOrBuyStockNumber = sellOrBuyStockNumber + 1

			// 计算当天买入的股票资产
			if util.DateToString(real9QuantStockTransactionRecord.BuyDate) == everyDate {
				_decimalValue := decimal.NewFromFloat(currentClosePrice)
				_decimalValue = _decimalValue.Mul(decimal.NewFromInt(int64(real9QuantStockTransactionRecord.BuyAmount)))
				_res, _ := decimalValue.Float64()
				_a := new(big.Rat).SetFloat64(currentBuyOrSellStockAssets)
				_b := new(big.Rat).SetFloat64(_res)
				currentBuyOrSellStockAssets, _ = new(big.Rat).Add(_a, _b).Float64()
			}
		}

		// 更新real9_q_account表
		r._real9QuantStockTransactionRecordDaoImpl.UpdateAfterBuy(*real9QuantAccount, everyDate, sellOrBuyStockNumber, stockAssets, currentBuyOrSellStockAssets)
	}
}

// 向real9_q_account_log表中插入进路
func (r *Real9StockTransactionRecordServiceImpl) insertLog(everyDate string) {
	pIo.Infoln("向表real9_q_account_log表中添加记录")

	// 返回量化账户
	var real9QuantAccountArray model.Real9QuantAccountArray = r._real9QuantAccountDaoImpl.FindAll()

	for _, real9QuantAccount := range real9QuantAccountArray {
		r._real9QuantAccountLogDaoImpl.Insert(everyDate, real9QuantAccount.AccountName)
	}
}

// 计算某一天所有股票的简单移动平均线、乖离率
func (r *Real9StockTransactionRecordServiceImpl) calculateBasicData(everyDate string) {
	// 计算某一天所有股票的简单移动平均线
	pIo.Infoln("开始计算某一天所有股票的简单移动平均线，日期[%s]", everyDate)
	r._real9QuantAccountLogDaoImpl.WriteMaByDate(everyDate)

	// 按照日期，计算所有股票在某一日的乖离率
	pIo.Infoln("开始按照日期，计算所有股票在某一日的乖离率，日期[%s]", everyDate)
	r._real9QuantAccountLogDaoImpl.WriteBiasByDate(everyDate)
}

/***************************************************************************** 优化方法 *****************************************************************************/

// 在卖出之前更新real9_o_account
func (r *Real9StockTransactionRecordServiceImpl) updateOptimizeAccountBeforeSell(everyDate string) {
	pIo.Infoln("在卖出之前更新real9_o_account")

	// 返回实盘优化账户
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAll()

	for _, real9OptimizeAccount := range real9OptimizeAccountArray {
		// 股票资产
		var stockAssets float64 = 0

		// 计算每一个实盘优化账户，在某一天卖股票前的收益
		var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(real9OptimizeAccount.AccountName)

		for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
			// 开盘价
			var currentClosePrice float64 = r.getRealOrHistoryClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)
			// 注意：如果没有查询到数据的话，则golang的float64类型数据默认是0
			if currentClosePrice == 0 {
				// 说明股票在这一天没有交易记录
				pIo.Infoln("股票[%s]在日期[%s]没有交易记录，开始查找前一个交易日的记录", real9OptimizeStockTransactionRecord.StockCode, everyDate)

				// 如果在某一天没有开盘价，比如停牌，则查找最近一个交易日的开盘价
				currentClosePrice = r._stockTransactionDataAllDaoImpl.FindLastClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)
			}

			// 计算这只股票的资产
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(real9OptimizeStockTransactionRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
		}

		// 更新real9_o_account表的stock_assets、total_assets字段
		if stockAssets != 0 {
			r._real9OptimizeAccountDaoImpl.UpdateBeforeSell(len(real9OptimizeStockTransactionRecordArray), stockAssets, real9OptimizeAccount.AccountName)
		}
	}
}

// 解决之前卖出失败的情况
func (r *Real9StockTransactionRecordServiceImpl) doOptimizeResolveFailSell(everyDate string) {
	pIo.Infoln("解决之前卖出失败的情况")

	// real9_o_account表的所有记录
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAll()

	for _, real9OptimizeAccount := range real9OptimizeAccountArray {
		// 如果这个账户没有持有股票，则查找下一个账户
		if real9OptimizeAccount.HoldStockNumber == 0 {
			pIo.Infoln("账号[%s]持股票数量为0，不需要卖出股票", (*real9OptimizeAccount).AccountName)
			continue
		}

		// 查询某个优化账户之前卖出失败的股票
		var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindOptimizeResolveFailSellByAccountName(real9OptimizeAccount.AccountName)

		for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
			// 查询股票
			var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9OptimizeStockTransactionRecord.StockCode, everyDate)

			// 如果没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录
			if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
				pIo.Infoln("股票[%s]在日期[%s]没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录", real9OptimizeStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 如果是一字跌停板，因此跳过这条记录
			if iUitl.OneWordLimitDown(stockTransactionDataAll, everyDate) {
				pIo.Infoln("股票[%s]在日期[%s]是一字跌停板，因此跳过这条记录", real9OptimizeStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 卖出
			r._real9OptimizeStockTransactionRecordDaoImpl.UpdateWhenSell(everyDate, stockTransactionDataAll, *real9OptimizeStockTransactionRecord)
		}
	}
}

// 退市卖出
func (r *Real9StockTransactionRecordServiceImpl) doOptimizeDelistSell(everyDate string) {
	pIo.Infoln("退市卖出")

	// optimize_account表的所有记录
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAll()

	for _, real9OptimizeAccount := range real9OptimizeAccountArray {
		// 如果这个账户没有持有股票，则查找下一个账户
		if real9OptimizeAccount.HoldStockNumber == 0 {
			pIo.Infoln("账号[%s]持股票数量为0，不需要卖出股票", (*real9OptimizeAccount).AccountName)
			continue
		}

		// 查询某个账号是否有退市的股票，如果有则卖出
		var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindDelistByLastTransactionDateAndAccountName(everyDate, real9OptimizeAccount.AccountName)

		for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
			// 查询股票
			var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9OptimizeStockTransactionRecord.StockCode, everyDate)

			// 由于这个是停牌、退市、摘牌的股票，因此一定要卖掉
			if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
				stockTransactionDataAll = r._stockTransactionDataAllDaoImpl.FindLastStockTransactionDataAllClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)
				pIo.Infoln("股票[%s]在日期[%s]停牌、退市、摘牌，因此强行卖掉这只股票", real9OptimizeStockTransactionRecord.StockCode, everyDate)
			}

			// 如果是一字跌停板，因此跳过这条记录
			// 因此这是最后一个交易日了，所以即使是一字跌停板，那也算是卖出了
			//if iUitl.OneWordLimitDown(stockTransactionDataAll, everyDate) {
			//	r._real9OptimizeStockTransactionRecordDaoImpl.UpdateFailSellReasonById(real9OptimizeStockTransactionRecord.ID, constants.LIMIT_DOWN)
			//	pIo.Infoln("股票[%s]在日期[%s]是一字跌停板，因此跳过这条记录", real9OptimizeStockTransactionRecord.StockCode, everyDate)
			//	continue
			//}

			// 卖出
			r._real9OptimizeStockTransactionRecordDaoImpl.UpdateWhenSell(everyDate, stockTransactionDataAll, *real9OptimizeStockTransactionRecord)
		}
	}
}

// 优化卖
func (r *Real9StockTransactionRecordServiceImpl) optimizeSell(everyDate string) {
	pIo.Infoln("优化卖")

	var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindBySellDate(everyDate)

	if real9QuantStockTransactionRecordArray != nil {
		for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
			// 查询股票
			var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockTransactionRecord.StockCode, everyDate)

			// 如果没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录
			if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
				r._real9OptimizeStockTransactionRecordDaoImpl.UpdateFailSellReasonById(real9QuantStockTransactionRecord.ID, constants.SUSPENSION)
				pIo.Infoln("股票[%s]在日期[%s]没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录", real9QuantStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 如果是一字跌停板，因此跳过这条记录
			if iUitl.OneWordLimitDown(stockTransactionDataAll, everyDate) {
				r._real9OptimizeStockTransactionRecordDaoImpl.UpdateFailSellReasonById(real9QuantStockTransactionRecord.ID, constants.LIMIT_DOWN)
				pIo.Infoln("股票[%s]在日期[%s]是一字跌停板，因此跳过这条记录", real9QuantStockTransactionRecord.StockCode, everyDate)
				continue
			}

			// 卖出
			r._real9OptimizeStockTransactionRecordDaoImpl.UpdateWhenOptimizeSell(*real9QuantStockTransactionRecord)
		}
	}
}

// 在卖出之后更新optimize_account
func (r *Real9StockTransactionRecordServiceImpl) updateOptimizeAccountAfterSell(everyDate string) {
	pIo.Infoln("在卖出之后更新real9_o_account")

	// 返回量化账户
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAll()

	for _, real9OptimizeAccount := range real9OptimizeAccountArray {
		// 持有股票的资产
		var holdStockAssets float64 = 0
		// 卖出股票的资产
		var sellStockAssets float64 = 0
		// 持股数量
		var sellOrBuyStockNumber int = 0

		// 计算每一个优化账户，在某一天卖完股票后持有股票的资产
		var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(real9OptimizeAccount.AccountName)

		for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
			// 查找某只股票在某一天的收盘价
			var currentClosePrice float64 = r.getRealOrHistoryClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)

			if currentClosePrice == 0 {
				// 如果在某一天没有开盘价，比如停牌，则查找最近一个交易日的开盘价
				currentClosePrice = r._stockTransactionDataAllDaoImpl.FindLastClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)
			}

			// 卖完股票后持有股票的资产、持股数量
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(real9OptimizeStockTransactionRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(holdStockAssets)
			b := new(big.Rat).SetFloat64(res)
			holdStockAssets, _ = new(big.Rat).Add(a, b).Float64()
			sellOrBuyStockNumber = sellOrBuyStockNumber + 1
		}

		// 计算每一个优化账户，在某一天卖完股票后卖出股票的资产
		var _real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndDateAndSellNotNull(real9OptimizeAccount.AccountName, everyDate)

		for _, real9OptimizeStockTransactionRecord := range _real9OptimizeStockTransactionRecordArray {
			// 查找某只股票在某一天的收盘价
			var currentClosePrice float64 = r.getRealOrHistoryClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)

			if currentClosePrice == 0 {
				// 如果在某一天没有开盘价，比如停牌，则查找最近一个交易日的开盘价
				currentClosePrice = r._stockTransactionDataAllDaoImpl.FindLastClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)
			}

			// 卖完股票后卖出股票的资产
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(real9OptimizeStockTransactionRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(sellStockAssets)
			b := new(big.Rat).SetFloat64(res)
			sellStockAssets, _ = new(big.Rat).Add(a, b).Float64()
		}

		// 更新real9_o_account表
		r._real9OptimizeAccountDaoImpl.UpdateAfterSell(sellOrBuyStockNumber, holdStockAssets, sellStockAssets, *real9OptimizeAccount)
	}
}

// 优化买
func (r *Real9StockTransactionRecordServiceImpl) doOptimizeBuy(everyDate string) {
	pIo.Infoln("优化买")

	// 查询real9_o_account表的记录
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAll()

	if real9OptimizeAccountArray != nil && len(real9OptimizeAccountArray) > 0 {
		for _, real9OptimizeAccount := range real9OptimizeAccountArray {

			var holdStockNumber int = real9OptimizeAccount.HoldStockNumber
			// 如果某个账号的持股数量已经到达最大持股数量，则跳过这个账号
			if holdStockNumber >= properties.Real9Properties_.MaxHoldStockNumber {
				pIo.Infoln("账号[%s]的持股数量已经到达[%d]只，不再买入股票", real9OptimizeAccount.AccountName, holdStockNumber)
				continue
			}

			// 根据账号名称，查询可以买入的股票
			var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r._real9QuantStockTransactionRecordDaoImpl.FindByAccountNameAndSellNullAndNotInReal9OptimizeStockTransactionRecord(real9OptimizeAccount.AccountName, everyDate)

			if real9QuantStockTransactionRecordArray != nil && len(real9QuantStockTransactionRecordArray) > 0 {
				for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {

					// 查询股票记录
					var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockTransactionRecord.StockCode, everyDate)
					if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
						pIo.Infoln("股票[%s]在日期[%s]没有交易记录，可能是停牌、退市、摘牌，跳过这只股票", real9QuantStockTransactionRecord.StockCode, everyDate)
						continue
					}
					//if stockTransactionDataAll.OpenPrice == stockTransactionDataAll.ClosePrice {
					//	pIo.Infoln("股票[%s]在日期[%s]的开盘价和收盘价一样，可能是一字涨停版，跳过这只股票", real9QuantStockTransactionRecord.StockCode, everyDate)
					//	continue
					//}
					if stockTransactionDataAll.OpenPrice < properties.Real9Properties_.OpenPriceBottomLimit {
						pIo.Infoln("股票[%s]在日期[%s]的开盘价为[%s]，小于[%s]，跳过这只股票", real9QuantStockTransactionRecord.StockCode, everyDate, stockTransactionDataAll.OpenPrice, properties.Real9Properties_.OpenPriceBottomLimit)
						continue
					}

					// 如果股票的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个账号
					if iUitl.CalculateBuyStockFee(stockTransactionDataAll.Code, stockTransactionDataAll.OpenPrice, 100) > float64(real9OptimizeAccount.CapitalAssets) {
						break
					}

					// 如果可以买，则向real9_o_stock_transact_record表中插入数据。
					// 计算应该买入股票的数量

					// 应当买入的股票的数量
					var shouldBuyStockNumber int = -1
					if len(real9QuantStockTransactionRecordArray) <= (properties.Real9Properties_.MaxHoldStockNumber - real9OptimizeAccount.HoldStockNumber) {
						shouldBuyStockNumber = len(real9QuantStockTransactionRecordArray)
					} else {
						shouldBuyStockNumber = properties.Real9Properties_.MaxHoldStockNumber - real9OptimizeAccount.HoldStockNumber
					}

					// 判断是否需要继续买入
					if shouldBuyStockNumber == 0 {
						pIo.Infoln("账号[%s]持股数量已经是%d，不再需要买入股票", real9OptimizeAccount.AccountName, properties.Real9Properties_.MaxHoldStockNumber)
						break
					}

					// 计算买多少股
					// 买入多少股
					var buyOrSellAmount int = 100

					for real9OptimizeAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9OptimizeAccount.HoldStockNumber) >= iUitl.CalculateBuyStockFee(real9QuantStockTransactionRecord.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) {
						if iUitl.CalculateBuyStockFee(real9QuantStockTransactionRecord.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) >= real9OptimizeAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9OptimizeAccount.HoldStockNumber) {
							break
						}
						buyOrSellAmount = buyOrSellAmount + 100
					}
					if real9OptimizeAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9OptimizeAccount.HoldStockNumber) < iUitl.CalculateBuyStockFee(real9QuantStockTransactionRecord.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) {
						if buyOrSellAmount == 100 {
							continue
						} else {
							buyOrSellAmount = buyOrSellAmount - 100
						}
					}

					// 向表real9_o_stock_transact_record中插入记录
					r._real9OptimizeStockTransactionRecordDaoImpl.Insert(real9OptimizeAccount.AccountName, real9QuantStockTransactionRecord.StockCode, everyDate,
						stockTransactionDataAll.OpenPrice, buyOrSellAmount,
						iUitl.CalculateRegistrationFee(real9QuantStockTransactionRecord.StockCode, buyOrSellAmount),
						iUitl.CalculateCommission(stockTransactionDataAll.OpenPrice, buyOrSellAmount))

					// 更新账号的持股数量
					holdStockNumber = holdStockNumber + 1

					// 如果某个账号的持股数量已经到达最大持股数量，则跳过这个账号
					if holdStockNumber >= properties.Real9Properties_.MaxHoldStockNumber {
						pIo.Infoln("账号[%s]的持股数量已经到达[%d]只，不再买入股票", real9OptimizeAccount.AccountName, holdStockNumber)
						break
					}
				}
			} else {
				pIo.Infoln("表real9_q_stock_transact_record中没有账号[%s]的持股记录，因此不再更新real9_q_stock_transact_record表", real9OptimizeAccount.AccountName)
			}
		}
	} else {
		pIo.Infoln("表real9_o_account中没有记录")
	}
}

// 在买入之后更新real9_o_account
func (r *Real9StockTransactionRecordServiceImpl) updateOptimizeAccountAfterBuy(everyDate string) {
	pIo.Infoln("在买入之后更新real9_o_account")

	// 返回量化账户
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAll()

	for _, real9OptimizeAccount := range real9OptimizeAccountArray {

		// 股票资产
		var stockAssets float64 = 0
		// 当天买入的股票资产
		var currentBuyOrSellStockAssets float64 = 0
		// 买入股票的数量
		var sellOrBuyStockNumber int = 0

		// 计算每一个量化账户，在某一天买完股票后的收益
		var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r._real9OptimizeStockTransactionRecordDaoImpl.FindByAccountNameAndSellNull(real9OptimizeAccount.AccountName)

		// 如果没有买股票，则直接将quant_account表中的记录插入到quant_account_log表中
		if real9OptimizeStockTransactionRecordArray == nil || len(real9OptimizeStockTransactionRecordArray) == 0 {
			// 向表quant_account_log中插入数据
			//u.db.Exec("insert into quant_account_log(DATE_, ACCOUNT_NAME, HOLD_STOCK_NUMBER, STOCK_ASSETS, "+
			//	"CAPITAL_ASSETS, TOTAL_ASSETS, TOTAL_STAMP_DUTY, TOTAL_REGISTRATE_FEE_WHEN_BUY, TOTAL_COMMISSION_WHEN_BUY, "+
			//	"TOTAL_REGISTRATE_FEE_WHEN_SELL, TOTAL_COMMISSION_WHEN_SELL) "+
			//	"select to_date(?, 'yyyy-mm-dd'), t.ACCOUNT_NAME, t.HOLD_STOCK_NUMBER, t.STOCK_ASSETS, t.CAPITAL_ASSETS, t.TOTAL_ASSETS, t.TOTAL_STAMP_DUTY, "+
			//	"t.TOTAL_REGISTRATE_FEE_WHEN_BUY, t.TOTAL_COMMISSION_WHEN_BUY, t.TOTAL_REGISTRATE_FEE_WHEN_SELL, t.TOTAL_COMMISSION_WHEN_SELL "+
			//	"from quant_account t where t.account_name = ?",
			//	transactionDate, (*quantAccount).AccountName)

			continue
		}

		for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
			// 查找某只股票在某一天的收盘价
			// 股票的收盘价
			var currentClosePrice float64 = r.getRealOrHistoryClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)
			// 注意：如果没有查询到数据的话，则golang的float64类型数据默认是0
			if currentClosePrice == 0 {
				// 说明股票在这一天没有交易记录
				pIo.Infoln("股票[%s]在日期[%s]没有交易记录，可能是停牌，开始查找前一个交易日的记录", real9OptimizeStockTransactionRecord.StockCode, everyDate)

				// 如果在某一天没有收盘价，比如停牌，则查找最近一个交易日的收盘价
				currentClosePrice = r._stockTransactionDataAllDaoImpl.FindLastClosePriceByByCodeAndDate(real9OptimizeStockTransactionRecord.StockCode, everyDate)
			}

			// 买入股票后的收益
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(real9OptimizeStockTransactionRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
			sellOrBuyStockNumber = sellOrBuyStockNumber + 1

			// 计算当天买入的股票资产
			if util.DateToString(real9OptimizeStockTransactionRecord.BuyDate) == everyDate {
				_decimalValue := decimal.NewFromFloat(currentClosePrice)
				_decimalValue = _decimalValue.Mul(decimal.NewFromInt(int64(real9OptimizeStockTransactionRecord.BuyAmount)))
				_res, _ := decimalValue.Float64()
				_a := new(big.Rat).SetFloat64(currentBuyOrSellStockAssets)
				_b := new(big.Rat).SetFloat64(_res)
				currentBuyOrSellStockAssets, _ = new(big.Rat).Add(_a, _b).Float64()
			}
		}

		// 更新real9_o_account表
		r._real9OptimizeAccountDaoImpl.UpdateAfterBuy(*real9OptimizeAccount, everyDate, sellOrBuyStockNumber, stockAssets, currentBuyOrSellStockAssets)
	}
}

// 执行，返回值为true表示已经减仓，否则为false
func (r *Real9StockTransactionRecordServiceImpl) underweight(everyDate string) {
	pIo.Infoln("根据牛熊线减仓，日期[%s]", everyDate)

	// 是否减仓了
	//var underweight bool = false

	var real9QuantAccountLogArray model.Real9QuantAccountLogArray = r._real9QuantAccountLogDaoImpl.FindByDate(everyDate)

	if nil != real9QuantAccountLogArray && len(real9QuantAccountLogArray) > 0 {
		for _, real9QuantAccountLog := range real9QuantAccountLogArray {
			// 如果对应账号的仓位已经空仓，则不用再减仓
			var real9OptimizeAccount model.Real9OptimizeAccount = r._real9OptimizeAccountDaoImpl.FindByAccountName(real9QuantAccountLog.AccountName)
			if real9OptimizeAccount.HoldStockNumber == 0 {
				continue
			}

			// 表示牛熊线
			var bullShortLine float64
			// 是否在牛熊线之下
			var belowBullShortLine bool = false
			if !belowBullShortLine && real9QuantAccountLog.Bias250 != 0 && real9QuantAccountLog.Bias250 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias250 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma250
				if real9QuantAccountLog.TotalAssets < bullShortLine {
					belowBullShortLine = true
				}
			}
			if !belowBullShortLine && real9QuantAccountLog.Bias120 != 0 && real9QuantAccountLog.Bias120 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias120 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma120
				if real9QuantAccountLog.TotalAssets < bullShortLine {
					belowBullShortLine = true
				}
			}
			if !belowBullShortLine && real9QuantAccountLog.Bias60 != 0 && real9QuantAccountLog.Bias60 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias60 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma60
				if real9QuantAccountLog.TotalAssets < bullShortLine {
					belowBullShortLine = true
				}
			}
			if !belowBullShortLine && real9QuantAccountLog.Bias20 != 0 && real9QuantAccountLog.Bias20 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias20 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma20
				if real9QuantAccountLog.TotalAssets < bullShortLine {
					belowBullShortLine = true
				}
			}
			if !belowBullShortLine && real9QuantAccountLog.Bias10 != 0 && real9QuantAccountLog.Bias10 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias10 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma10
				if real9QuantAccountLog.TotalAssets < bullShortLine {
					belowBullShortLine = true
				}
			}
			if !belowBullShortLine && real9QuantAccountLog.Bias5 != 0 && real9QuantAccountLog.Bias5 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias5 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma5
				if real9QuantAccountLog.TotalAssets < bullShortLine {
					belowBullShortLine = true
				}
			}
			// 如果最后任何bias指标都无法确定哪一根均线可以作为牛熊线的话，则将前一个交易日的总资产作为牛熊线
			bullShortLine = r._real9QuantAccountLogDaoImpl.FindLastTotalAssetsByAccountNameAndDate(real9QuantAccountLog.AccountName, everyDate)
			if real9QuantAccountLog.TotalAssets < bullShortLine {
				belowBullShortLine = true
			}

			// 减仓
			if belowBullShortLine {
				//underweight = true
				var overOrUnderWeightAmount int = properties.Real9Properties_.OverOrUnderWeightAmount
				// 查询可以减仓的股票
				var real9OptimizeStockTransactionRecordArray model.Real9OptimizeStockTransactionRecordArray = r.getRealOptimizeStockTransactRecordArrayByAccountNameAndDateAndSellNull(real9QuantAccountLog.AccountName, everyDate)
				if nil != real9OptimizeStockTransactionRecordArray && len(real9OptimizeStockTransactionRecordArray) > 0 {
					for _, real9OptimizeStockTransactionRecord := range real9OptimizeStockTransactionRecordArray {
						if overOrUnderWeightAmount > 0 {
							var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9OptimizeStockTransactionRecord.StockCode, everyDate)

							// 如果没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录
							if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
								r._real9OptimizeStockTransactionRecordDaoImpl.UpdateFailSellReasonById(real9OptimizeStockTransactionRecord.ID, constants.SUSPENSION)
								pIo.Infoln("股票[%s]在日期[%s]没有查找到记录，可能是因为这个股票在这个交易日停牌、退市、摘牌，因此跳过这条记录", real9OptimizeStockTransactionRecord.StockCode, everyDate)
								continue
							}

							// 如果是一字跌停板，因此跳过这条记录
							if iUitl.OneWordLimitDown(stockTransactionDataAll, everyDate) {
								r._real9OptimizeStockTransactionRecordDaoImpl.UpdateFailSellReasonById(real9OptimizeStockTransactionRecord.ID, constants.LIMIT_DOWN)
								pIo.Infoln("股票[%s]在日期[%s]是一字跌停板，因此跳过这条记录", real9OptimizeStockTransactionRecord.StockCode, everyDate)
								continue
							}

							// 更新real9_o_stock_transact_record
							r._real9OptimizeStockTransactionRecordDaoImpl.UpdateWhenOptimizeSell_underweight(everyDate, stockTransactionDataAll, *real9OptimizeStockTransactionRecord)
							overOrUnderWeightAmount--
						} else {
							break
						}
					}
				}
			}
		}
	}
	//return underweight
}

// 返回值为true表示已经加仓，否则为false
func (r *Real9StockTransactionRecordServiceImpl) overweight(everyDate string) {
	pIo.Infoln("根据牛熊线加仓，日期[%s]", everyDate)

	// 是否加仓了
	//var overweight bool = false

	var real9QuantAccountLogArray model.Real9QuantAccountLogArray = r._real9QuantAccountLogDaoImpl.FindByDate(everyDate)

	if nil != real9QuantAccountLogArray && len(real9QuantAccountLogArray) > 0 {
		for _, real9QuantAccountLog := range real9QuantAccountLogArray {
			// 如果对应账号的仓位已满，则不用再加仓
			var real9OptimizeAccount model.Real9OptimizeAccount = r._real9OptimizeAccountDaoImpl.FindByAccountName(real9QuantAccountLog.AccountName)
			if real9OptimizeAccount.HoldStockNumber == properties.Real9Properties_.MaxHoldStockNumber {
				continue
			}

			// 表示牛熊线
			var bullShortLine float64
			// 是否在牛熊线之上
			var aboveBullShortLine bool = false
			if !aboveBullShortLine && real9QuantAccountLog.Bias250 != 0 && real9QuantAccountLog.Bias250 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias250 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma250
				if real9QuantAccountLog.TotalAssets >= bullShortLine {
					aboveBullShortLine = true
				}
			}
			if !aboveBullShortLine && real9QuantAccountLog.Bias120 != 0 && real9QuantAccountLog.Bias120 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias120 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma120
				if real9QuantAccountLog.TotalAssets >= bullShortLine {
					aboveBullShortLine = true
				}
			}
			if !aboveBullShortLine && real9QuantAccountLog.Bias60 != 0 && real9QuantAccountLog.Bias60 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias60 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma60
				if real9QuantAccountLog.TotalAssets >= bullShortLine {
					aboveBullShortLine = true
				}
			}
			if !aboveBullShortLine && real9QuantAccountLog.Bias20 != 0 && real9QuantAccountLog.Bias20 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias20 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma20
				if real9QuantAccountLog.TotalAssets >= bullShortLine {
					aboveBullShortLine = true
				}
			}
			if !aboveBullShortLine && real9QuantAccountLog.Bias10 != 0 && real9QuantAccountLog.Bias10 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias10 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma10
				if real9QuantAccountLog.TotalAssets >= bullShortLine {
					aboveBullShortLine = true
				}
			}
			if !aboveBullShortLine && real9QuantAccountLog.Bias5 != 0 && real9QuantAccountLog.Bias5 <= properties.Real9Properties_.BiasThresholdTop && real9QuantAccountLog.Bias5 >= properties.Real9Properties_.BiasThresholdBottom {
				bullShortLine = real9QuantAccountLog.Ma5
				if real9QuantAccountLog.TotalAssets >= bullShortLine {
					aboveBullShortLine = true
				}
			}
			// 如果最后任何bias指标都无法确定哪一根均线可以作为牛熊线的话，则将前一个交易日的总资产作为牛熊线
			bullShortLine = r._real9QuantAccountLogDaoImpl.FindLastTotalAssetsByAccountNameAndDate(real9QuantAccountLog.AccountName, everyDate)
			if real9QuantAccountLog.TotalAssets >= bullShortLine {
				aboveBullShortLine = true
			}

			// 加仓
			if aboveBullShortLine {
				//overweight = true
				var overOrUnderWeightAmount int = properties.Real9Properties_.OverOrUnderWeightAmount
				// 查询可以加仓的股票
				var real9QuantStockTransactionRecordArray model.Real9QuantStockTransactionRecordArray = r.getRealQuantStockTransactRecordArrayByAccountNameAndDateAndSellNull(real9QuantAccountLog.AccountName, everyDate)
				//if len(real9QuantStockTransactionRecordArray) == 10 {
				//	pIo.Infoln("")
				//}
				//if nil != real9QuantStockTransactionRecordArray && len(real9QuantStockTransactionRecordArray) < 10 {
				if nil != real9QuantStockTransactionRecordArray && len(real9QuantStockTransactionRecordArray) > 0 {
					for _, real9QuantStockTransactionRecord := range real9QuantStockTransactionRecordArray {
						if overOrUnderWeightAmount > 0 {
							// 查询股票记录
							var stockTransactionDataAll model.StockTransactionDataAll = r.getRealOrHistoryStockTransactionDataAll(real9QuantStockTransactionRecord.StockCode, everyDate)
							if stockTransactionDataAll.Code == "" || stockTransactionDataAll.OpenPrice == 0 {
								pIo.Infoln("股票在日期[%s]没有交易记录，可能是停牌、退市、摘牌，跳过这只股票", everyDate)

								continue
							}

							// 如果股票的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个账号
							if iUitl.CalculateBuyStockFee(stockTransactionDataAll.Code, stockTransactionDataAll.ClosePrice, 100) > float64(real9OptimizeAccount.CapitalAssets) {
								break
							}

							// 如果可以买，则向optimize_stock_transact_record表中插入数据。
							// 计算应该买入股票的数量

							// 应当买入的股票的数量
							var shouldBuyStockNumber int = -1
							if len(real9QuantStockTransactionRecordArray) <= (properties.Real9Properties_.MaxHoldStockNumber - real9OptimizeAccount.HoldStockNumber) {
								shouldBuyStockNumber = len(real9QuantStockTransactionRecordArray)
							} else {
								shouldBuyStockNumber = properties.Real9Properties_.MaxHoldStockNumber - real9OptimizeAccount.HoldStockNumber
							}

							// 判断是否需要继续买入
							if shouldBuyStockNumber == 0 {
								pIo.Infoln("账号[%s]持股数量已经是%d，不再需要买入股票", real9OptimizeAccount.AccountName, properties.Real9Properties_.MaxHoldStockNumber)
								break
							}

							// 计算买多少股
							// 买入多少股
							var buyOrSellAmount int = 100

							for real9OptimizeAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9OptimizeAccount.HoldStockNumber) >= iUitl.CalculateBuyStockFee(real9QuantStockTransactionRecord.StockCode, stockTransactionDataAll.ClosePrice, buyOrSellAmount) {
								if iUitl.CalculateBuyStockFee(real9QuantStockTransactionRecord.StockCode, stockTransactionDataAll.ClosePrice, buyOrSellAmount) >= real9OptimizeAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9OptimizeAccount.HoldStockNumber) {
									break
								}
								buyOrSellAmount = buyOrSellAmount + 100
							}
							if real9OptimizeAccount.CapitalAssets/float64(properties.Real9Properties_.MaxHoldStockNumber-real9OptimizeAccount.HoldStockNumber) < iUitl.CalculateBuyStockFee(real9QuantStockTransactionRecord.StockCode, stockTransactionDataAll.ClosePrice, buyOrSellAmount) {
								if buyOrSellAmount == 100 {
									continue
								} else {
									buyOrSellAmount = buyOrSellAmount - 100
								}
							}

							// 插入记录
							r._real9OptimizeStockTransactionRecordDaoImpl.Insert(real9OptimizeAccount.AccountName, real9QuantStockTransactionRecord.StockCode, everyDate,
								stockTransactionDataAll.ClosePrice, buyOrSellAmount,
								iUitl.CalculateRegistrationFee(real9QuantStockTransactionRecord.StockCode, buyOrSellAmount),
								iUitl.CalculateCommission(stockTransactionDataAll.ClosePrice, buyOrSellAmount))
							overOrUnderWeightAmount--
						} else {
							break
						}
					}
				}
			}
		}
	}
	//return overweight
}

// 向表real9_o_account_log表中添加记录
func (r *Real9StockTransactionRecordServiceImpl) insetReal9OptimizeAccountLog(everyDate string) {
	pIo.Infoln("向表real9_o_account_log表中添加记录")

	// 返回量化账户
	var real9OptimizeAccountArray model.Real9OptimizeAccountArray = r._real9OptimizeAccountDaoImpl.FindAll()

	for _, real9OptimizeAccount := range real9OptimizeAccountArray {
		r._real9OptimizeAccountLogDaoImpl.Insert(everyDate, real9OptimizeAccount.AccountName)
	}
}

// 开始计算ma数据
func (r *Real9StockTransactionRecordServiceImpl) writeMa(everyDate string) {
	pIo.Infoln("开始计算ma数据，日期[%s]", everyDate)

	r._real9OptimizeAccountLogDaoImpl.WriteMaByDate(everyDate)
}

// 开始计算bias数据
func (r *Real9StockTransactionRecordServiceImpl) writeBias(everyDate string) {
	pIo.Infoln("开始计算bias数据，日期[%s]", everyDate)

	r._real9OptimizeAccountLogDaoImpl.WriteBiasByDate(everyDate)
}
